"use client";

import type React from "react";
import { useState } from "react";
import { cx } from "../lib/utils";
import { OnboardingButton } from "../primitives/onboarding-button";
import { OnboardingInput } from "../primitives/onboarding-input";
import { OnboardingLabel } from "../primitives/onboarding-label";
import {
	OnboardingSelect,
	OnboardingSelectContent,
	OnboardingSelectItem,
	OnboardingSelectTrigger,
	OnboardingSelectValue,
} from "../primitives/onboarding-select";

export interface SelectOption {
	value: string;
	label: string;
}

export interface TextInputField {
	/** Unique identifier for the field */
	id: string;
	/** Label displayed above the input */
	label: string;
	/** Placeholder text */
	placeholder?: string;
	/** Optional description/helper text */
	description?: string;
	/** Field type: 'text' for input, 'select' for dropdown */
	fieldType?: "text" | "select";
	/** Input type (text, email, url, etc.) - only for text fields */
	type?: "text" | "email" | "url" | "tel";
	/** Options for select fields */
	options?: SelectOption[];
	/** Whether the field is required */
	required?: boolean;
	/** Validation pattern (regex string) */
	pattern?: string;
	/** Error message for invalid input */
	errorMessage?: string;
	/** Default value */
	defaultValue?: string;
}

export interface TextInputStepProps {
	/** Title displayed at the top of the step */
	title?: string;
	/** Description text below the title */
	description?: string;
	/** Array of text input fields */
	fields: TextInputField[];
	/** Called when any value changes */
	onValuesChange?: (values: Record<string, string>) => void;
	/** Called when the user submits the form */
	onSubmit: (values: Record<string, string>) => void | Promise<void>;
	/** Text for the submit button */
	submitText?: string;
	/** Text shown while submitting */
	loadingText?: string;
	/** Optional back button config */
	backButton?: {
		text: string;
		onClick: () => void;
	};
}

export function TextInputStep({
	title = "Enter your details",
	description = "Please fill in the information below.",
	fields,
	onValuesChange,
	onSubmit,
	submitText = "Continue",
	loadingText = "Submitting...",
	backButton,
}: TextInputStepProps) {
	const [values, setValues] = useState<Record<string, string>>(() => {
		const initial: Record<string, string> = {};
		fields.forEach((field) => {
			initial[field.id] = field.defaultValue ?? "";
		});
		return initial;
	});
	const [errors, setErrors] = useState<Record<string, string>>({});
	const [touched, setTouched] = useState<Record<string, boolean>>({});
	const [loading, setLoading] = useState(false);

	const validateField = (
		field: TextInputField,
		value: string,
	): string | null => {
		if (field.required && !value?.trim()) {
			return field.errorMessage || `${field.label} is required`;
		}
		if (field.fieldType === "select") {
			// Select fields only need required validation
			return null;
		}
		if (field.pattern && value) {
			const regex = new RegExp(field.pattern);
			if (!regex.test(value)) {
				return field.errorMessage || `Invalid ${field.label.toLowerCase()}`;
			}
		}
		if (field.type === "email" && value) {
			const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
			if (!emailRegex.test(value)) {
				return field.errorMessage || "Please enter a valid email address";
			}
		}
		if (field.type === "url" && value) {
			try {
				new URL(value);
			} catch {
				return field.errorMessage || "Please enter a valid URL";
			}
		}
		return null;
	};

	const handleChange = (fieldId: string, value: string) => {
		const newValues = { ...values, [fieldId]: value };
		setValues(newValues);
		onValuesChange?.(newValues);

		// Clear error on change if field was touched
		if (touched[fieldId]) {
			const field = fields.find((f) => f.id === fieldId);
			if (field) {
				const error = validateField(field, value);
				setErrors((prev) => ({ ...prev, [fieldId]: error || "" }));
			}
		}
	};

	const handleBlur = (fieldId: string) => {
		setTouched((prev) => ({ ...prev, [fieldId]: true }));
		const field = fields.find((f) => f.id === fieldId);
		if (field) {
			const error = validateField(field, values[fieldId]);
			setErrors((prev) => ({ ...prev, [fieldId]: error || "" }));
		}
	};

	const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
		e.preventDefault();

		// Validate all fields
		const newErrors: Record<string, string> = {};
		const newTouched: Record<string, boolean> = {};
		let hasErrors = false;

		fields.forEach((field) => {
			newTouched[field.id] = true;
			const error = validateField(field, values[field.id]);
			if (error) {
				newErrors[field.id] = error;
				hasErrors = true;
			}
		});

		setTouched(newTouched);
		setErrors(newErrors);

		if (hasErrors) return;

		setLoading(true);
		try {
			await onSubmit(values);
		} finally {
			setLoading(false);
		}
	};

	const isValid = fields.every((field) => {
		if (field.required && !values[field.id]?.trim()) return false;
		return !errors[field.id];
	});

	return (
		<main className="mx-auto p-4">
			<div
				style={{ animationDuration: "500ms" }}
				className="motion-safe:animate-in motion-safe:fade-in motion-safe:slide-in-from-bottom-4"
			>
				<h1 className="text-2xl font-semibold text-foreground sm:text-xl">
					{title}
				</h1>
				<p className="mt-6 text-muted-foreground sm:text-sm">{description}</p>
			</div>

			<form onSubmit={handleSubmit} className="mt-8">
				<div className="flex flex-col gap-6">
					{fields.map((field, index) => (
						<div
							key={field.id}
							className="motion-safe:animate-in motion-safe:fade-in motion-safe:slide-in-from-bottom-4"
							style={{
								animationDuration: "500ms",
								animationDelay: `${100 + index * 100}ms`,
								animationFillMode: "backwards",
							}}
						>
							<OnboardingLabel
								className="mb-2 block text-sm font-medium text-foreground"
								htmlFor={field.id}
							>
								{field.label}
								{field.required && (
									<span className="ml-1 text-destructive">*</span>
								)}
							</OnboardingLabel>

							{field.description && (
								<p className="mb-2 text-sm text-muted-foreground">
									{field.description}
								</p>
							)}

							{field.fieldType === "select" ? (
								<OnboardingSelect
									value={values[field.id]}
									onValueChange={(value) => {
										handleChange(field.id, value);
										setTouched((prev) => ({ ...prev, [field.id]: true }));
									}}
								>
									<OnboardingSelectTrigger
										id={field.id}
										className={cx(
											touched[field.id] &&
												errors[field.id] &&
												"border-destructive",
										)}
									>
										<OnboardingSelectValue placeholder={field.placeholder} />
									</OnboardingSelectTrigger>
									<OnboardingSelectContent>
										{field.options?.map((option) => (
											<OnboardingSelectItem
												key={option.value}
												value={option.value}
											>
												{option.label}
											</OnboardingSelectItem>
										))}
									</OnboardingSelectContent>
								</OnboardingSelect>
							) : (
								<OnboardingInput
									id={field.id}
									type={field.type || "text"}
									placeholder={field.placeholder}
									value={values[field.id]}
									onChange={(e) => handleChange(field.id, e.target.value)}
									onBlur={() => handleBlur(field.id)}
									aria-invalid={touched[field.id] && !!errors[field.id]}
									aria-describedby={
										errors[field.id] ? `${field.id}-error` : undefined
									}
									className={cx(
										touched[field.id] &&
											errors[field.id] &&
											"border-destructive",
									)}
								/>
							)}

							{touched[field.id] && errors[field.id] && (
								<p
									id={`${field.id}-error`}
									className="mt-1.5 text-sm text-destructive"
								>
									{errors[field.id]}
								</p>
							)}
						</div>
					))}
				</div>

				<div
					className={cx(
						"mt-8 flex",
						backButton ? "justify-between" : "justify-end",
					)}
				>
					{backButton && (
						<OnboardingButton
							type="button"
							variant="ghost"
							onClick={backButton.onClick}
						>
							{backButton.text}
						</OnboardingButton>
					)}
					<OnboardingButton
						className="disabled:bg-muted disabled:text-muted-foreground"
						type="submit"
						disabled={!isValid || loading}
						aria-disabled={!isValid || loading}
						isLoading={loading}
					>
						{loading ? loadingText : submitText}
					</OnboardingButton>
				</div>
			</form>
		</main>
	);
}
