import React from "react";
import { __ } from "@wordpress/i18n";
import { ChevronDown, ChevronRight, ChevronUp, Copy, Plus, Trash2 } from "lucide-react";
import AjaxSelect from "./AjaxSelect";

export const ELEMENT_TYPES = [
	{ value: "product", label: __("Product (single item)", "arraysubs") },
	{ value: "categories", label: __("Product Categories", "arraysubs") },
	{ value: "text", label: __("Text Input", "arraysubs") },
	{ value: "textarea", label: __("Textarea", "arraysubs") },
	{ value: "checkbox", label: __("Checkbox (single/multi)", "arraysubs") },
	{ value: "select", label: __("Select", "arraysubs") },
	{ value: "multiselect", label: __("Multi Select", "arraysubs") },
	{ value: "upload", label: __("Upload", "arraysubs") },
];

export const elementTypeLabel = (type) =>
	ELEMENT_TYPES.find((entry) => entry.value === type)?.label || type;

export const makeId = (prefix) =>
	`${prefix}_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;

export const defaultSettingsForType = (type, uploadMaxMb) => {
	switch (type) {
		case "product":
			return { product_id: 0, max_qty: 1 };
		case "categories":
			return { category_ids: [], min_count: 0, max_count: 0 };
		case "text":
		case "textarea":
			return { placeholder: "" };
		case "checkbox":
			return { mode: "single", options: [] };
		case "select":
		case "multiselect":
			return { options: [{ value: "", label: "" }] };
		case "upload":
			return { max_size_mb: Math.min(5, uploadMaxMb), allowed_types: ["images"] };
		default:
			return {};
	}
};

const OptionsEditor = ({ options, onChange }) => (
	<div className="arraysubs-box-options-editor">
		{options.map((option, index) => (
			// eslint-disable-next-line react/no-array-index-key
			<div className="arraysubs-box-options-editor__row" key={index}>
				<input
					type="text"
					value={option.label}
					placeholder={__("Option label", "arraysubs")}
					onChange={(event) => {
						const next = options.map((row, i) =>
							i === index ? { label: event.target.value, value: event.target.value } : row
						);
						onChange(next);
					}}
				/>
				<button
					type="button"
					className="button arraysubs-box-icon-btn"
					onClick={() => onChange(options.filter((row, i) => i !== index))}
					aria-label={__("Remove option", "arraysubs")}
				>
					<Trash2 size={13} />
				</button>
			</div>
		))}
		<button
			type="button"
			className="button arraysubs-box-add-option"
			onClick={() => onChange([...options, { value: "", label: "" }])}
		>
			<Plus size={13} />
			{__("Add Option", "arraysubs")}
		</button>
	</div>
);

/**
 * One element row inside a step: collapsible, type-driven settings.
 */
const ElementRow = ({
	element,
	index,
	total,
	collapsed,
	onToggleCollapse,
	onChange,
	onDelete,
	onDuplicate,
	onMove,
	uploadMaxMb,
	schedule,
}) => {
	const update = (updates) => onChange({ ...element, ...updates });
	const updateSettings = (updates) => update({ settings: { ...element.settings, ...updates } });

	const changeType = (type) =>
		onChange({
			...element,
			type,
			settings: defaultSettingsForType(type, uploadMaxMb),
		});

	const summary = element.label || elementTypeLabel(element.type);

	return (
		<div className={`arraysubs-box-element-row${collapsed ? " is-collapsed" : ""}`}>
			<div className="arraysubs-box-element-row__header">
				<button
					type="button"
					className="arraysubs-box-element-row__collapse"
					onClick={onToggleCollapse}
					aria-expanded={!collapsed}
				>
					<ChevronRight
						size={14}
						className={`arraysubs-box-collapse-icon${collapsed ? "" : " is-expanded"}`}
					/>
				</button>
				<span className="arraysubs-box-element-row__type-badge">
					{elementTypeLabel(element.type)}
				</span>
				<span className="arraysubs-box-element-row__summary">{summary}</span>
				{element.required && (
					<span className="arraysubs-box-element-row__required-badge">
						{__("Required", "arraysubs")}
					</span>
				)}
				<span className="arraysubs-box-element-row__actions">
					<button
						type="button"
						className="button arraysubs-box-icon-btn"
						disabled={index === 0}
						onClick={() => onMove(index, index - 1)}
						aria-label={__("Move up", "arraysubs")}
					>
						<ChevronUp size={13} />
					</button>
					<button
						type="button"
						className="button arraysubs-box-icon-btn"
						disabled={index === total - 1}
						onClick={() => onMove(index, index + 1)}
						aria-label={__("Move down", "arraysubs")}
					>
						<ChevronDown size={13} />
					</button>
					<button
						type="button"
						className="button arraysubs-box-icon-btn"
						onClick={onDuplicate}
						aria-label={__("Duplicate element", "arraysubs")}
					>
						<Copy size={13} />
					</button>
					<button
						type="button"
						className="button arraysubs-box-icon-btn arraysubs-box-icon-btn--danger"
						onClick={onDelete}
						aria-label={__("Delete element", "arraysubs")}
					>
						<Trash2 size={13} />
					</button>
				</span>
			</div>

			{!collapsed && (
				<div className="arraysubs-box-element-row__body">
					<div className="arraysubs-box-field-grid">
						<label className="arraysubs-box-field-item">
							<span>{__("Element Type", "arraysubs")}</span>
							<select value={element.type} onChange={(event) => changeType(event.target.value)}>
								{ELEMENT_TYPES.map((entry) => (
									<option key={entry.value} value={entry.value}>
										{entry.label}
									</option>
								))}
							</select>
							<small>
								{__(
									"Product and Product Categories fill the box; the rest collect answers. Changing the type resets this element's settings.",
									"arraysubs"
								)}
							</small>
						</label>
						<label className="arraysubs-box-field-item">
							<span>{__("Label", "arraysubs")}</span>
							<input
								type="text"
								value={element.label}
								placeholder={__("Shown to the customer", "arraysubs")}
								onChange={(event) => update({ label: event.target.value })}
							/>
							<small>
								{__(
									"Heading above this element on the storefront. Leave empty to show no heading.",
									"arraysubs"
								)}
							</small>
						</label>
						<label className="arraysubs-box-field-item arraysubs-box-field-item--toggle">
							<span>{__("Required", "arraysubs")}</span>
							<span className="arraysubs-box-toggle">
								<input
									type="checkbox"
									checked={!!element.required}
									onChange={(event) => update({ required: event.target.checked })}
								/>
								<span className="arraysubs-box-toggle__slider" />
							</span>
							<small>{__("Blocks add-to-cart until answered.", "arraysubs")}</small>
						</label>
					</div>

					{element.type === "product" && (
						<div className="arraysubs-box-field-grid">
							<div className="arraysubs-box-field-item arraysubs-box-field-item--wide">
								<span>{__("Product", "arraysubs")}</span>
								<AjaxSelect
									value={element.settings.product_id}
									onChange={(product_id) => updateSettings({ product_id })}
									endpoint="box-products"
									schedule={schedule}
									placeholder={__("Search products…", "arraysubs")}
								/>
								<small>
									{__(
										"Only simple products that can share this box's billing cycle are listed. Type at least 3 characters to search.",
										"arraysubs"
									)}
								</small>
							</div>
							<label className="arraysubs-box-field-item">
								<span>{__("Max Quantity", "arraysubs")}</span>
								<input
									type="number"
									min="1"
									step="1"
									value={element.settings.max_qty}
									onChange={(event) =>
										updateSettings({ max_qty: Math.max(1, parseInt(event.target.value, 10) || 1) })
									}
								/>
								<small>
									{__("How many of this item one customer may take.", "arraysubs")}
								</small>
							</label>
						</div>
					)}

					{element.type === "categories" && (
						<div className="arraysubs-box-field-grid">
							<div className="arraysubs-box-field-item arraysubs-box-field-item--wide">
								<span>{__("Categories", "arraysubs")}</span>
								<AjaxSelect
									value={element.settings.category_ids}
									onChange={(category_ids) => updateSettings({ category_ids })}
									endpoint="box-categories"
									schedule={schedule}
									multiple
									placeholder={__("Search categories…", "arraysubs")}
								/>
								<small>
									{__(
										"Every eligible product in these categories becomes a card the customer can pick, up to 100 products per element. Categories with nothing eligible are not offered.",
										"arraysubs"
									)}
								</small>
							</div>
							<label className="arraysubs-box-field-item">
								<span>{__("Min Items", "arraysubs")}</span>
								<input
									type="number"
									min="0"
									step="1"
									value={element.settings.min_count}
									onChange={(event) =>
										updateSettings({ min_count: Math.max(0, parseInt(event.target.value, 10) || 0) })
									}
								/>
								<small>
									{__(
										"0 = no minimum. Turning Required on makes the minimum 1.",
										"arraysubs"
									)}
								</small>
							</label>
							<label className="arraysubs-box-field-item">
								<span>{__("Max Items", "arraysubs")}</span>
								<input
									type="number"
									min="0"
									step="1"
									value={element.settings.max_count}
									onChange={(event) =>
										updateSettings({ max_count: Math.max(0, parseInt(event.target.value, 10) || 0) })
									}
								/>
								<small>
									{__(
										"0 = unlimited. Both limits count the total quantity picked across this element, not the number of different products.",
										"arraysubs"
									)}
								</small>
							</label>
						</div>
					)}

					{(element.type === "text" || element.type === "textarea") && (
						<div className="arraysubs-box-field-grid">
							<label className="arraysubs-box-field-item arraysubs-box-field-item--wide">
								<span>{__("Placeholder", "arraysubs")}</span>
								<input
									type="text"
									value={element.settings.placeholder}
									onChange={(event) => updateSettings({ placeholder: event.target.value })}
								/>
								<small>
									{element.type === "textarea"
										? __(
												"Grey hint shown in the empty field. The answer is stored with the order, up to 5,000 characters.",
												"arraysubs"
										  )
										: __(
												"Grey hint shown in the empty field. The answer is stored with the order, up to 500 characters.",
												"arraysubs"
										  )}
								</small>
							</label>
						</div>
					)}

					{element.type === "checkbox" && (
						<div className="arraysubs-box-field-grid">
							<label className="arraysubs-box-field-item">
								<span>{__("Mode", "arraysubs")}</span>
								<select
									value={element.settings.mode}
									onChange={(event) =>
										updateSettings({
											mode: event.target.value,
											options:
												event.target.value === "multi" && element.settings.options.length === 0
													? [{ value: "", label: "" }]
													: element.settings.options,
										})
									}
								>
									<option value="single">{__("Single", "arraysubs")}</option>
									<option value="multi">{__("Multi", "arraysubs")}</option>
								</select>
								<small>
									{__(
										"Single shows one tick box using the label above and stores “Yes”. Multi shows one tick box per option.",
										"arraysubs"
									)}
								</small>
							</label>
							{element.settings.mode === "multi" && (
								<div className="arraysubs-box-field-item arraysubs-box-field-item--wide">
									<span>{__("Options", "arraysubs")}</span>
									<OptionsEditor
										options={element.settings.options}
										onChange={(options) => updateSettings({ options })}
									/>
									<small>
										{__(
											"The label is what the customer sees and what is stored with the order. At least one option is needed.",
											"arraysubs"
										)}
									</small>
								</div>
							)}
						</div>
					)}

					{(element.type === "select" || element.type === "multiselect") && (
						<div className="arraysubs-box-field-grid">
							<div className="arraysubs-box-field-item arraysubs-box-field-item--wide">
								<span>{__("Options", "arraysubs")}</span>
								<OptionsEditor
									options={element.settings.options}
									onChange={(options) => updateSettings({ options })}
								/>
								<small>
									{element.type === "multiselect"
										? __(
												"Shown as tick boxes so the customer can pick several. The label is what is stored with the order.",
												"arraysubs"
										  )
										: __(
												"Shown as a dropdown with a “Choose an option…” placeholder added automatically. The label is what is stored with the order.",
												"arraysubs"
										  )}
								</small>
							</div>
						</div>
					)}

					{element.type === "upload" && (
						<div className="arraysubs-box-field-grid">
							<label className="arraysubs-box-field-item">
								<span>{__("Max File Size (MB)", "arraysubs")}</span>
								<input
									type="number"
									min="1"
									max={uploadMaxMb}
									step="1"
									value={element.settings.max_size_mb}
									onChange={(event) =>
										updateSettings({
											max_size_mb: Math.min(
												uploadMaxMb,
												Math.max(1, parseInt(event.target.value, 10) || 1)
											),
										})
									}
								/>
								<small>
									{__("Site upload limit:", "arraysubs")} {uploadMaxMb} MB
									{" — "}
									{__("this cap can never be set above it.", "arraysubs")}
								</small>
							</label>
							<div className="arraysubs-box-field-item">
								<span>{__("Allowed File Types", "arraysubs")}</span>
								<div className="arraysubs-box-check-group">
									{["images", "pdf", "csv"].map((group) => (
										<label key={group} className="arraysubs-box-check">
											<input
												type="checkbox"
												checked={element.settings.allowed_types.includes(group)}
												onChange={(event) => {
													const current = element.settings.allowed_types;
													const next = event.target.checked
														? [...current, group]
														: current.filter((g) => g !== group);
													updateSettings({
														allowed_types: next.length > 0 ? next : ["images"],
													});
												}}
											/>
											<span>
												{group === "images"
													? __("Images", "arraysubs")
													: group.toUpperCase()}
											</span>
										</label>
									))}
								</div>
								<small>
									{__(
										"Files are checked by content, not by extension, and stored outside the media library. Unticking everything falls back to Images.",
										"arraysubs"
									)}
								</small>
							</div>
						</div>
					)}
				</div>
			)}
		</div>
	);
};

export default ElementRow;
