import React, { useEffect, useLayoutEffect, useRef, useState } from "react";
import {
	getContentGateData,
	getContentGateLocalizedData,
} from "../../../utils/localized-data";
import { __ } from "@wordpress/i18n";
import CheckboxRadioInput from "./CheckboxRadioInput";
import { ConditionType } from "../../../types";

type Props = {
	type: string;
	field: string;
	value: any;
	operator: string;
	onChange: (newValue: any) => void;
	uniqueId: string;
	placeholder?: string;
	existingConditions: ConditionType[];
};

const ConditionValueInput = ({
	type,
	field,
	value,
	operator,
	onChange,
	uniqueId,
	placeholder,
	existingConditions,
}: Props) => {
	const cgData = getContentGateLocalizedData();

	// Normalize initial value: for checkbox, ensure it's a scalar; for multiselect, ensure it's an array
	const normalizeValue = (val: any, inputType: string) => {
		if (inputType === "multiselect") {
			return Array.isArray(val) ? val : val ? [val] : [];
		} else if (inputType === "checkbox") {
			// For checkbox, always return a scalar value
			let normalizedVal;
			if (Array.isArray(val)) {
				normalizedVal = val.length > 0 ? val[0] : "";
			} else {
				normalizedVal = val || "";
			}
			// Convert old format (logged_in/logged_out) to new format (logged-in/logged-out) for user_state
			if (field === "user_state") {
				if (normalizedVal === "logged_in") {
					normalizedVal = "logged-in";
				} else if (normalizedVal === "logged_out") {
					normalizedVal = "logged-out";
				}
			}
			return normalizedVal;
		}
		return val || "";
	};

	const [inputValue, setInputValue] = useState(normalizeValue(value, type));
	const selectRef = useRef(null);

	useEffect(() => {
		setInputValue(normalizeValue(value, type));
	}, [value, type]);

	const handleChange = (newValue: any) => {
		setInputValue(newValue);
		onChange(newValue);
	};

	// Initialize select2 for multiselect type only
	// Use useLayoutEffect for synchronous DOM updates to prevent visible delay
	useLayoutEffect(() => {
		if (type === "multiselect" && selectRef.current) {
			const $select = window.jQuery(selectRef.current);

			// Destroy existing select2 instance if any
			if ($select.hasClass("select2-hidden-accessible")) {
				$select.select2("destroy");
			}

			// Initialize select2 immediately - DOM is ready in useLayoutEffect
			var select2_changed_flag_up = false;

			$select
				.select2({
					containerCssClass: $select.data("select2_class"),
				})
				.on("select2:selecting", function () {
					select2_changed_flag_up = true;
				})
				.on("select2:unselecting", function () {
					select2_changed_flag_up = true;
				})
				.on("select2:closing", function (this: HTMLSelectElement) {
					if (select2_changed_flag_up && this.multiple) {
						select2_changed_flag_up = false;
						return false;
					}
				})
				.on("change", function (e: Event) {
					// Sync select2 changes with React state
					const target = e.target as HTMLSelectElement;
					const selected = Array.from(
						target.selectedOptions,
						(option) => option.value,
					);
					handleChange(selected);
				});

			// Set initial value
			if (Array.isArray(inputValue) && inputValue.length > 0) {
				$select.val(inputValue).trigger("change");
			}

			// Cleanup on unmount
			return () => {
				if ($select && $select.hasClass("select2-hidden-accessible")) {
					$select.off(
						"change select2:selecting select2:unselecting select2:closing",
					);
					$select.select2("destroy");
				}
			};
		}
	}, [type, field]); // Initialize when type, field state changes

	// Sync select2 value when inputValue changes externally (from props)
	useEffect(() => {
		if (type === "multiselect" && selectRef.current) {
			const $select = window.jQuery(selectRef.current);
			if ($select.hasClass("select2-hidden-accessible")) {
				// Only update if value actually changed to avoid loops
				const currentVal = $select.val() || [];
				const currentArray = Array.isArray(currentVal)
					? currentVal
					: currentVal
						? [currentVal]
						: [];
				const newArray = Array.isArray(inputValue)
					? inputValue
					: inputValue
						? [inputValue]
						: [];
				if (
					JSON.stringify(currentArray.sort()) !==
					JSON.stringify(newArray.sort())
				) {
					$select.val(inputValue).trigger("change");
				}
			}
		}
	}, [inputValue, type]);

	// Hide input if operator is "empty" or "not empty"
	if (operator === "empty" || operator === "not empty") {
		return null;
	}

	// Get options for multiselect fields from contentgate_localized_data
	const getOptions = () => {
		const labels = getContentGateData("labels", {});

		switch (field) {
			case "roles":
				const wpRoles = getContentGateData("wp_roles", {});
				return Object.entries(wpRoles).map(([id, label]) => ({
					value: id,
					label: label || id,
				}));

			case "user_state":
				return [
					{
						value: "logged-in",
						label:
							labels.logged_in || __("Logged In", "contentgate"),
					},
					{
						value: "logged-out",
						label:
							labels.logged_out ||
							__("Logged Out", "contentgate"),
					},
				];

			default:
				return [];
		}
	};

	// Get selected role values from other role conditions
	const getSelectedRolesFromOtherConditions = (): string[] => {
		if (field !== "roles") return [];

		return existingConditions
			.filter(
				(cond: any) =>
					cond.type === "condition" &&
					cond.value === "roles" &&
					cond.id !== uniqueId,
			)
			.flatMap((cond: any) =>
				Array.isArray(cond.conditionValue)
					? cond.conditionValue
					: cond.conditionValue
						? [cond.conditionValue]
						: [],
			);
	};

	switch (type) {
		case "checkbox":
			// Render radio buttons for checkbox type
			return (
				<CheckboxRadioInput
					field={field}
					value={inputValue}
					onChange={handleChange}
					uniqueId={uniqueId}
				/>
			);

		case "multiselect":
			const options = getOptions();
			const selectedInOtherRows = getSelectedRolesFromOtherConditions();

			// Handle both array and single value for multiselect
			const selectedValues = Array.isArray(inputValue)
				? inputValue
				: inputValue
					? [inputValue]
					: [];

			const handleMultiSelectChange = (
				e: React.ChangeEvent<HTMLSelectElement>,
			) => {
				// This handler is mainly for non-select2 scenarios
				// select2 changes are handled in the useEffect
				const selected = Array.from(
					e.target.selectedOptions,
					(option) => option.value,
				);
				handleChange(selected);
			};

			return (
				<select
					ref={selectRef}
					className="components-select-control__input contentgate-enhanced-select2 contentgate-condition-value-select contentgate-condition-value-select--multiselect !max-w-[160px] xs:!max-w-full xl2:!max-w-[190px] !w-full !min-h-[38px] "
					value={selectedValues}
					onChange={handleMultiSelectChange}
					multiple={true}
				>
					{options.map((option) => {
						const isDisabled =
							field === "roles" &&
							selectedInOtherRows.includes(option.value) &&
							!selectedValues.includes(option.value);

						return (
							<option
								key={option.value}
								value={option.value}
								disabled={isDisabled}
							>
								{option.label}
							</option>
						);
					})}
				</select>
			);

		case "text":
		default:
			return (
				<input
					type="text"
					className="components-text-control__input contentgate-condition-value-input contentgate-condition-value-text"
					value={inputValue}
					onChange={(e) => handleChange(e.target.value)}
					placeholder={
						placeholder || __("Enter value", "contentgate")
					}
				/>
			);
	}
};

export default ConditionValueInput;
