import React, { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { __, sprintf } from "@wordpress/i18n";
import { ArrowLeft, ArrowRight, Save, Settings2 } from "lucide-react";
import Modal from "@libs/modal";
import { useConfirm } from "@libs/confirm-dialog";
import StepsBuilder, { makeDefaultStep } from "./StepsBuilder";
import DiscountBuilder from "./DiscountBuilder";
import ScheduleSection, { scheduleLabel } from "./ScheduleSection";
import SyncRenewalsBuilder from "./SyncRenewalsBuilder";
import { elementTypeLabel } from "./ElementRow";

const WIZARD_STEPS = [
	__("Box Steps", "arraysubs"),
	__("Discounts & Freebies", "arraysubs"),
	__("Flexible Renewal Sync", "arraysubs"),
];

const EMPTY_CONFIG = {
	schedule: { period: "month", interval: 1, length: 0, keep_signup_fees: false },
	steps: [],
	discounts: {
		basis: "total_value",
		max_value: 0,
		boundaries: [],
		ranges: [{ freebies: [], discount: { type: "none", amount: 0 } }],
	},
	renewal_sync: {
		enabled: false,
		seg1_end: 0,
		seg2_end: 0,
		seg1_active: true,
		seg2_active: true,
		seg3_active: true,
	},
};

const normalizeSchedule = (raw) => {
	const source = raw && typeof raw === "object" ? raw : {};
	const period = ["day", "week", "month", "year"].includes(source.period) ? source.period : "month";
	return {
		period,
		interval: Math.min(12, Math.max(1, parseInt(source.interval, 10) || 1)),
		length: Math.min(365, Math.max(0, parseInt(source.length, 10) || 0)),
		keep_signup_fees: !!source.keep_signup_fees,
	};
};

const normalizeSync = (raw) => {
	const source = raw && typeof raw === "object" ? raw : {};
	const sync = {
		enabled: !!source.enabled,
		seg1_end: Math.max(0, parseInt(source.seg1_end, 10) || 0),
		seg2_end: Math.max(0, parseInt(source.seg2_end, 10) || 0),
		seg1_active: source.seg1_active !== false,
		seg2_active: source.seg2_active !== false,
		seg3_active: source.seg3_active !== false,
	};
	if (!sync.seg1_active && !sync.seg2_active && !sync.seg3_active) {
		sync.seg1_active = true;
		sync.seg2_active = true;
		sync.seg3_active = true;
	}
	return sync;
};

const normalizeConfig = (raw) => {
	if (!raw || typeof raw !== "object") {
		return JSON.parse(JSON.stringify(EMPTY_CONFIG));
	}
	const steps = Array.isArray(raw.steps) ? raw.steps : [];
	const discounts = raw.discounts && typeof raw.discounts === "object" ? raw.discounts : {};
	const basis = discounts.basis === "total_count" ? "total_count" : "total_value";
	const rawMaxValue = Number(discounts.max_value);
	const maxValue =
		Number.isFinite(rawMaxValue) && rawMaxValue > 0
			? basis === "total_count"
				? Math.round(rawMaxValue)
				: Math.round(rawMaxValue * 100) / 100
			: 0;
	const boundaries = Array.isArray(discounts.boundaries)
		? discounts.boundaries.map(Number).filter((b) => b > 0)
		: [];
	boundaries.sort((a, b) => a - b);
	let ranges = Array.isArray(discounts.ranges) ? discounts.ranges : [];
	ranges = ranges.slice(0, boundaries.length + 1);
	while (ranges.length < boundaries.length + 1) {
		ranges.push({ freebies: [], discount: { type: "none", amount: 0 } });
	}
	return {
		schedule: normalizeSchedule(raw.schedule),
		renewal_sync: normalizeSync(raw.renewal_sync),
		steps: steps.map((step) => ({
			id: step.id || `step_${Math.random().toString(36).substr(2, 9)}`,
			title: step.title || "",
			elements: Array.isArray(step.elements)
				? step.elements.map((element) => ({
						id: element.id || `el_${Math.random().toString(36).substr(2, 9)}`,
						type: element.type || "categories",
						label: element.label || "",
						required: !!element.required,
						settings: element.settings || {},
				  }))
				: [],
		})),
		discounts: {
			basis,
			max_value: maxValue,
			boundaries,
			ranges: ranges.map((range) => ({
				freebies: Array.isArray(range.freebies) ? range.freebies.map(Number).filter(Boolean) : [],
				discount: {
					type: ["fixed", "percent"].includes(range?.discount?.type)
						? range.discount.type
						: "none",
					amount: Number(range?.discount?.amount) || 0,
				},
			})),
		},
	};
};

const validateWorkingConfig = (config) => {
	if (config.steps.length === 0) {
		return __("Add at least one box step.", "arraysubs");
	}
	for (const step of config.steps) {
		if (!step.title.trim()) {
			return __("Every step needs a title.", "arraysubs");
		}
		if (step.elements.length === 0) {
			return sprintf(
				/* translators: %s: step title. */
				__('Step "%s" has no elements.', "arraysubs"),
				step.title
			);
		}
		for (const element of step.elements) {
			if (element.type === "product" && !Number(element.settings.product_id)) {
				return sprintf(
					/* translators: %s: step title. */
					__('A product element in "%s" has no product selected.', "arraysubs"),
					step.title
				);
			}
			if (
				element.type === "categories" &&
				(!Array.isArray(element.settings.category_ids) ||
					element.settings.category_ids.length === 0)
			) {
				return sprintf(
					/* translators: %s: step title. */
					__('A categories element in "%s" has no categories selected.', "arraysubs"),
					step.title
				);
			}
			if (
				["select", "multiselect"].includes(element.type) &&
				(element.settings.options || []).filter((option) => (option.label || "").trim()).length === 0
			) {
				return sprintf(
					/* translators: %s: step title. */
					__('A select element in "%s" has no options.', "arraysubs"),
					step.title
				);
			}
			if (
				element.type === "checkbox" &&
				element.settings.mode === "multi" &&
				(element.settings.options || []).filter((option) => (option.label || "").trim()).length === 0
			) {
				return sprintf(
					/* translators: %s: step title. */
					__('A multi checkbox element in "%s" has no options.', "arraysubs"),
					step.title
				);
			}
		}
	}

	const hasProductSource = config.steps.some((step) =>
		step.elements.some((element) => ["product", "categories"].includes(element.type))
	);
	if (!hasProductSource) {
		return __("Add at least one product or categories element so customers can fill the box.", "arraysubs");
	}

	return null;
};

const validateDiscountConfig = (config) => {
	const maxValue = Number(config?.discounts?.max_value);
	if (!Number.isFinite(maxValue) || maxValue <= 0) {
		return __("Enter a maximum value before configuring ranges.", "arraysubs");
	}
	return null;
};

/**
 * Read-only box summary + "Configure Box" button opening the two-screen
 * modal wizard (Box Steps → Discounts & Freebies). Saved config is synced
 * into the hidden input and travels with the normal product save.
 */
const BoxConfigEditor = ({ initialConfig, inputSelector }) => {
	const env = window.arraySubsBox || {};
	const [config, setConfig] = useState(() => normalizeConfig(initialConfig));
	const [isModalOpen, setIsModalOpen] = useState(false);
	// 0 = schedule + box steps, 1 = discounts & freebies, 2 = sync renewals
	const [modalScreen, setModalScreen] = useState(0);
	const [workingConfig, setWorkingConfig] = useState(null);
	const [validationMessage, setValidationMessage] = useState("");
	const { confirm, confirmDialog } = useConfirm();
	const editorRef = useRef(null);

	// Keep the hidden input in sync so WooCommerce saves the config.
	useEffect(() => {
		const input = document.querySelector(inputSelector);
		if (input) {
			const isEmpty = config.steps.length === 0;
			input.value = isEmpty ? "" : JSON.stringify(config);
			input.dispatchEvent(new Event("change", { bubbles: true }));
		}
	}, [config, inputSelector]);

	const openModal = useCallback(() => {
		const working = JSON.parse(JSON.stringify(config));
		if (working.steps.length === 0) {
			working.steps = [makeDefaultStep(0)];
		}
		setWorkingConfig(working);
		setModalScreen(0);
		setValidationMessage("");
		setIsModalOpen(true);
	}, [config]);

	const closeModal = useCallback(() => {
		setIsModalOpen(false);
		setWorkingConfig(null);
		setValidationMessage("");
	}, []);

	// Any forward move validates the box steps first — later screens depend on
	// a coherent step configuration.
	const goToScreen = (screen) => {
		if (screen > 0) {
			const error = validateWorkingConfig(workingConfig);
			if (error) {
				setValidationMessage(error);
				setModalScreen(0);
				return;
			}
		}
		if (screen > 1) {
			const error = validateDiscountConfig(workingConfig);
			if (error) {
				setValidationMessage(error);
				setModalScreen(1);
				return;
			}
		}
		setValidationMessage("");
		setModalScreen(screen);
	};

	const saveConfig = () => {
		const stepsError = validateWorkingConfig(workingConfig);
		if (stepsError) {
			setValidationMessage(stepsError);
			setModalScreen(0);
			return;
		}
		const discountsError = validateDiscountConfig(workingConfig);
		if (discountsError) {
			setValidationMessage(discountsError);
			setModalScreen(1);
			return;
		}
		setConfig(JSON.parse(JSON.stringify(workingConfig)));
		closeModal();
	};

	const summary = useMemo(() => {
		const elementCount = config.steps.reduce((sum, step) => sum + step.elements.length, 0);
		return { stepCount: config.steps.length, elementCount };
	}, [config]);

	const formatPoint = (value) =>
		config.discounts.basis === "total_count"
			? String(Math.round(value))
			: `${env.currencySymbol || ""}${Number(value).toFixed(2).replace(/\.00$/, "")}`;

	const rangeBoundsLabel = (index) => {
		const bounds = config.discounts.boundaries;
		const from = index === 0 ? 0 : bounds[index - 1];
		if (index >= bounds.length) {
			return sprintf(
				/* translators: %s: range start. */
				__("%s and above", "arraysubs"),
				formatPoint(from)
			);
		}
		return `${formatPoint(from)} – ${formatPoint(bounds[index])}`;
	};

	return (
		<div className="arraysubs-box-editor" ref={editorRef}>
			<div className="arraysubs-box-editor__summary-bar">
				<button type="button" className="button arraysubs-box-configure-btn" onClick={openModal}>
					<Settings2 size={14} />
					{summary.stepCount === 0
						? __("Configure Box", "arraysubs")
						: __("Edit Box Configuration", "arraysubs")}
				</button>
				{summary.stepCount > 0 && (
					<span className="arraysubs-box-editor__count">
						{sprintf(
							/* translators: 1: steps count, 2: elements count. */
							__("%1$d step(s), %2$d element(s)", "arraysubs"),
							summary.stepCount,
							summary.elementCount
						)}
					</span>
				)}
			</div>

			{summary.stepCount === 0 && (
				<div className="arraysubs-box-editor__empty">
					{__("No box configuration yet. Customers cannot purchase this box until steps are configured.", "arraysubs")}
				</div>
			)}

			{summary.stepCount > 0 && (
				<div className="arraysubs-box-editor__preview">
					<div className="arraysubs-box-facts">
						<div className="arraysubs-box-fact">
							<span className="arraysubs-box-fact__label">{__("Billing", "arraysubs")}</span>
							<span className="arraysubs-box-fact__value">
								{scheduleLabel(config.schedule)}
								{config.schedule.length > 0
									? ` · ${sprintf(
											/* translators: %d: number of billing cycles. */
											__("%d cycles", "arraysubs"),
											config.schedule.length
									  )}`
									: ` · ${__("until cancelled", "arraysubs")}`}
							</span>
						</div>
						<div className="arraysubs-box-fact">
							<span className="arraysubs-box-fact__label">
								{__("Signup fees", "arraysubs")}
							</span>
							<span className="arraysubs-box-fact__value">
								{config.schedule.keep_signup_fees
									? __("Summed from box contents", "arraysubs")
									: __("Not charged", "arraysubs")}
							</span>
						</div>
						<div className="arraysubs-box-fact">
							<span className="arraysubs-box-fact__label">
								{__("Flexible renewal sync", "arraysubs")}
							</span>
							<span className="arraysubs-box-fact__value">
								{/* Off is not "no syncing" — the box falls back to the store-wide setting. */}
								{config.renewal_sync.enabled
									? __("Custom segment plan", "arraysubs")
									: __("Store default", "arraysubs")}
							</span>
						</div>
					</div>

					<table className="arraysubs-box-summary-table">
						<thead>
							<tr>
								<th>{__("Step", "arraysubs")}</th>
								<th>{__("Elements", "arraysubs")}</th>
							</tr>
						</thead>
						<tbody>
							{config.steps.map((step, index) => (
								<tr key={step.id}>
									<td>
										<strong>
											{index + 1}. {step.title}
										</strong>
									</td>
									<td>
										{step.elements
											.map(
												(element) =>
													`${elementTypeLabel(element.type)}${
														element.required ? " *" : ""
													}${element.label ? ` (${element.label})` : ""}`
											)
											.join(", ")}
									</td>
								</tr>
							))}
						</tbody>
					</table>

					<table className="arraysubs-box-summary-table arraysubs-box-summary-table--ranges">
						<thead>
							<tr>
								<th>
									{config.discounts.basis === "total_count"
										? __("Range (item count)", "arraysubs")
										: __("Range (box value)", "arraysubs")}
								</th>
								<th>{__("Discount", "arraysubs")}</th>
								<th>{__("Freebies", "arraysubs")}</th>
							</tr>
						</thead>
						<tbody>
							{config.discounts.ranges.map((range, index) => (
								// eslint-disable-next-line react/no-array-index-key
								<tr key={index}>
									<td>{rangeBoundsLabel(index)}</td>
									<td>
										{range.discount.type === "none" && "—"}
										{range.discount.type === "percent" && `${range.discount.amount}%`}
										{range.discount.type === "fixed" &&
											`${env.currencySymbol || ""}${Number(range.discount.amount).toFixed(2)}`}
									</td>
									<td>
										{range.freebies.length === 0
											? "—"
											: sprintf(
													/* translators: %d: freebie count. */
													__("%d product(s)", "arraysubs"),
													range.freebies.length
											  )}
									</td>
								</tr>
							))}
						</tbody>
					</table>
				</div>
			)}

			<Modal
				isOpen={isModalOpen}
				onClose={closeModal}
				title={__("Configure Subscription Box", "arraysubs")}
				size="full"
				className="arraysubs-box-modal-editor"
				closeOnBackdrop={false}
			>
				{workingConfig && (
					<div className="arraysubs-box-modal-editor__inner">
						<div className="arraysubs-box-wizard-nav">
							{WIZARD_STEPS.map((label, index) => (
								<React.Fragment key={label}>
									{index > 0 && <span className="arraysubs-box-wizard-nav__divider" />}
									<button
										type="button"
										className={`arraysubs-box-wizard-nav__step${
											modalScreen === index ? " is-active" : ""
										}`}
										onClick={() => goToScreen(index)}
									>
										<span className="arraysubs-box-wizard-nav__index">{index + 1}</span>
										{label}
									</button>
								</React.Fragment>
							))}
						</div>

						{validationMessage && (
							<div className="arraysubs-box-validation-notice" role="alert">
								{validationMessage}
							</div>
						)}

						<div className="arraysubs-box-modal-editor__screen">
							{modalScreen === 0 && (
								<>
									<ScheduleSection
										schedule={workingConfig.schedule}
										onChange={(schedule) => setWorkingConfig({ ...workingConfig, schedule })}
									/>
									<div className="arraysubs-box-section">
										<div className="arraysubs-box-section__head">
											<h3 className="arraysubs-box-section__title">
												{__("Box Steps", "arraysubs")}
											</h3>
											<p className="arraysubs-box-section__desc">
												{__(
													"Each step is one screen the customer walks through. Add the products, categories and questions that belong on it.",
													"arraysubs"
												)}
											</p>
										</div>
										<StepsBuilder
											steps={workingConfig.steps}
											onChange={(steps) => setWorkingConfig({ ...workingConfig, steps })}
											uploadMaxMb={Number(env.uploadMaxMb) || 5}
											confirm={confirm}
											schedule={workingConfig.schedule}
										/>
									</div>
								</>
							)}
							{modalScreen === 1 && (
								<DiscountBuilder
									discounts={workingConfig.discounts}
									onChange={(discounts) => setWorkingConfig({ ...workingConfig, discounts })}
									currencySymbol={env.currencySymbol || ""}
								/>
							)}
							{modalScreen === 2 && (
								<SyncRenewalsBuilder
									sync={workingConfig.renewal_sync}
									schedule={workingConfig.schedule}
									onChange={(renewal_sync) =>
										setWorkingConfig({ ...workingConfig, renewal_sync })
									}
								/>
							)}
						</div>

						<div className="arraysubs-box-modal-editor__actions">
							<button type="button" className="button" onClick={closeModal}>
								{__("Cancel", "arraysubs")}
							</button>
							<span className="arraysubs-box-modal-editor__actions-spacer" />
							{modalScreen > 0 && (
								<button
									type="button"
									className="button"
									onClick={() => goToScreen(modalScreen - 1)}
								>
									<ArrowLeft size={14} />
									{__("Back", "arraysubs")}
								</button>
							)}
							{modalScreen < WIZARD_STEPS.length - 1 ? (
								<button
									type="button"
									className="button button-primary"
									onClick={() => goToScreen(modalScreen + 1)}
								>
									{sprintf(
										/* translators: %s: next step name. */
										__("Continue to %s", "arraysubs"),
										WIZARD_STEPS[modalScreen + 1]
									)}
									<ArrowRight size={14} />
								</button>
							) : (
								<button type="button" className="button button-primary" onClick={saveConfig}>
									<Save size={14} />
									{__("Save Configuration", "arraysubs")}
								</button>
							)}
						</div>
					</div>
				)}
			</Modal>

			{confirmDialog}
		</div>
	);
};

export default BoxConfigEditor;
