"use client";

import type React from "react";
import { useEffect, useMemo, useState } from "react";
import { cx } from "../lib/utils";
import { OnboardingButton } from "../primitives/onboarding-button";
import { OnboardingCard } from "../primitives/onboarding-card";
import { OnboardingInput } from "../primitives/onboarding-input";
import { OnboardingLabel } from "../primitives/onboarding-label";
import { OnboardingSlider } from "../primitives/onboarding-slider";

export interface ScaleField {
	/** Unique identifier for the field */
	id: string;
	/** Label displayed above the input */
	label: string;
	/** Optional description text */
	description?: string;
	/** Minimum value */
	min: number;
	/** Maximum value */
	max: number;
	/** Step increment (default: 1) */
	step?: number;
	/** Default/initial value */
	defaultValue?: number;
	/** Unit label (e.g., "requests/mo", "GB", "users") */
	unit?: string;
	/** Custom value formatter for display (e.g., "10K", "1M") */
	formatValue?: (value: number) => string;
	/** Whether to show a slider (default: true) */
	showSlider?: boolean;
}

export interface ScaleInputStepProps {
	/** Title displayed at the top of the step */
	title?: string;
	/** Description text below the title */
	description?: string;
	/** Array of scale fields to display */
	fields: ScaleField[];
	/** Called when any value changes */
	onValuesChange?: (values: Record<string, number>) => void;
	/** Called when the user submits the form */
	onSubmit: (values: Record<string, number>) => 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;
	};
	/** Optional summary card config */
	summary?: {
		label: string;
		calculate: (values: Record<string, number>) => string;
	};
}

function defaultFormatValue(value: number): string {
	if (value >= 1_000_000_000) {
		return `${(value / 1_000_000_000).toFixed(1)}B`;
	}
	if (value >= 1_000_000) {
		return `${(value / 1_000_000).toFixed(1)}M`;
	}
	if (value >= 1_000) {
		return `${(value / 1_000).toFixed(1)}K`;
	}
	return value.toString();
}

interface FieldInputProps {
	field: ScaleField;
	value: number;
	onChange: (value: number) => void;
	animationDelay: number;
}

function FieldInput({
	field,
	value,
	onChange,
	animationDelay,
}: FieldInputProps) {
	const displayValue = field.formatValue
		? field.formatValue(value)
		: defaultFormatValue(value);
	const showSlider = field.showSlider !== false;

	return (
		<div
			className="space-y-3 motion-safe:animate-in motion-safe:fade-in motion-safe:slide-in-from-bottom-4"
			style={{
				animationDuration: "500ms",
				animationDelay: `${animationDelay}ms`,
				animationFillMode: "backwards",
			}}
		>
			<div className="flex items-baseline justify-between gap-4">
				<OnboardingLabel
					className="text-base font-medium text-foreground sm:text-sm"
					htmlFor={field.id}
				>
					{field.label}
				</OnboardingLabel>
				{field.unit && (
					<span className="text-sm text-muted-foreground">{field.unit}</span>
				)}
			</div>

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

			<div className="flex items-center gap-4">
				{showSlider ? (
					<>
						<OnboardingSlider
							id={field.id}
							value={[value]}
							onValueChange={([newValue]) => onChange(newValue)}
							min={field.min}
							max={field.max}
							step={field.step || 1}
							aria-valuetext={`${displayValue} ${field.unit || ""}`}
							className="flex-1"
						/>
						<div className="flex h-8 min-w-16 items-center justify-center rounded border border-border bg-background px-2 text-sm font-medium text-foreground">
							<span>{displayValue}</span>
						</div>
					</>
				) : (
					<OnboardingInput
						id={field.id}
						type="number"
						min={field.min}
						max={field.max}
						step={field.step || 1}
						value={value}
						onChange={(e) => onChange(Number(e.target.value))}
						className="max-w-32"
					/>
				)}
			</div>
		</div>
	);
}

export function ScaleInputStep({
	title = "Configure your scale",
	description = "Help us understand your expected usage.",
	fields,
	onValuesChange,
	onSubmit,
	submitText = "Continue",
	loadingText = "Submitting...",
	backButton,
	summary,
}: ScaleInputStepProps) {
	const [values, setValues] = useState<Record<string, number>>(() => {
		const initial: Record<string, number> = {};
		fields.forEach((field) => {
			initial[field.id] = field.defaultValue ?? field.min;
		});
		return initial;
	});
	const [loading, setLoading] = useState(false);

	useEffect(() => {
		onValuesChange?.(values);
	}, [values, onValuesChange]);

	const handleFieldChange = (fieldId: string, value: number) => {
		setValues((prev) => ({
			...prev,
			[fieldId]: value,
		}));
	};

	const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
		e.preventDefault();
		setLoading(true);
		try {
			await onSubmit(values);
		} finally {
			setLoading(false);
		}
	};

	const summaryValue = useMemo(() => {
		if (summary) {
			return summary.calculate(values);
		}
		return null;
	}, [summary, values]);

	const isValid = fields.every((field) => {
		const value = values[field.id];
		return value >= field.min && value <= field.max;
	});

	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-8">
					{fields.map((field, index) => (
						<FieldInput
							key={field.id}
							field={field}
							value={values[field.id]}
							onChange={(value) => handleFieldChange(field.id, value)}
							animationDelay={200 + index * 150}
						/>
					))}

					{summary && summaryValue && (
						<OnboardingCard
							className="mt-4 space-y-1 border-border motion-safe:animate-in motion-safe:fade-in motion-safe:slide-in-from-bottom-4"
							style={{
								animationDuration: "500ms",
								animationDelay: `${200 + fields.length * 150}ms`,
								animationFillMode: "backwards",
							}}
						>
							<p className="text-muted-foreground sm:text-sm">
								{summary.label}
							</p>
							<p
								className="text-3xl font-medium text-foreground sm:text-2xl"
								aria-live="polite"
							>
								{summaryValue}
							</p>
						</OnboardingCard>
					)}

					<div
						className={cx(
							"mt-6 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>
				</div>
			</form>
		</main>
	);
}
