"use client"

import { useRef, useState, useEffect } from "react"
import { useFormContext, useController, useWatch } from "react-hook-form"
import { useQuery } from "@tanstack/react-query"
import { Loader2 } from "lucide-react"
import { useAuthApi } from "@/shared/useApi"
import { Field, FieldLabel, FieldError } from "@/shared/components/ui/field"
import {
    Combobox,
    ComboboxInput,
    ComboboxContent,
    ComboboxList,
    ComboboxItem,
    ComboboxEmpty,
} from "@/shared/components/ui/combobox"
import type { VehicleFormValues } from "./vehicle.schema"

// ── Helpers ──

function toOptionalString(value: unknown): string | undefined {
    if (typeof value === "string") return value || undefined
    if (typeof value === "number") return String(value)
    return undefined
}

function unique(values: unknown[]): string[] {
    return [...new Set(values.map(toOptionalString).filter((v): v is string => !!v))].sort()
}

// ── Internal combobox for a single free-text + suggestion field ──

type VehicleComboboxProps = {
    value: string
    onChange: (value: string) => void
    onBlur?: () => void
    options: string[]
    loading?: boolean
    placeholder: string
    label: string
    error?: string
    required?: boolean
    disabled?: boolean
}

function normalizeTextValue(value: unknown): string {
    if (typeof value === "string") return value
    if (typeof value === "number") return String(value)
    return ""
}

function VehicleCombobox({
    value,
    onChange,
    onBlur,
    options,
    loading,
    placeholder,
    label,
    error,
    required,
    disabled,
}: VehicleComboboxProps) {
    const anchorRef = useRef<HTMLDivElement>(null)

    // Local state keeps the input text in sync even when the form value
    // is changed externally (e.g., cascade reset or edit-mode population).
    const [inputText, setInputText] = useState(() => normalizeTextValue(value))

    useEffect(() => {
        setInputText(normalizeTextValue(value))
    }, [value])

    // Client-side filtering of suggestions based on what's been typed
    const normalizedInput = normalizeTextValue(inputText).toLowerCase()
    const filtered = options.filter((opt) =>
        !normalizedInput || opt.toLowerCase().includes(normalizedInput),
    )

    return (
        <Field data-invalid={!!error || undefined}>
            <FieldLabel>
                {label}
                {required && <span className="text-destructive ms-0.5">*</span>}
            </FieldLabel>
            <div ref={anchorRef}>
                <Combobox

                    value={normalizeTextValue(inputText) || null}
                    onValueChange={(val) => {
                        const str = val !== null ? String(val) : ""
                        setInputText(str)
                        onChange(str)
                    }}
                    disabled={disabled}
                    onInputValueChange={(text, { reason }) => {
                        if (reason === "input-change") {
                            const next = normalizeTextValue(text)
                            setInputText(next)
                            onChange(next)
                        }
                    }}
                >
                    <ComboboxInput
                        placeholder={placeholder}
                        showClear={normalizeTextValue(inputText).length > 0}
                        onBlur={onBlur}
                        aria-invalid={!!error || undefined}

                    />
                    {(loading || filtered.length > 0) && (
                        <ComboboxContent anchor={anchorRef}>
                            <ComboboxList>
                                {!loading &&
                                    filtered.map((opt) => (
                                        <ComboboxItem key={opt} value={opt}>
                                            {opt}
                                        </ComboboxItem>
                                    ))}
                            </ComboboxList>
                        </ComboboxContent>
                    )}
                </Combobox>
            </div>
            {error && <FieldError>{error}</FieldError>}
        </Field>
    )
}

// ── Main composite field ──

/**
 * Manages the four vehicle identity fields (make, model, year, sub_model) as
 * a single coordinated component.  Each field shows autocomplete suggestions
 * fetched from the make-and-models API, filtered by the values of the
 * preceding fields.  All four fields accept free-text — the user is never
 * forced to pick from the suggestion list.
 *
 * Cascade behaviour: changing make resets model → year → sub_model;
 * changing model resets year → sub_model; changing year resets sub_model.
 */
export function RhfVehicleIdentityField() {
    const api = useAuthApi()
    const { control, setValue } = useFormContext<VehicleFormValues>()

    // Read shop_type to pass as shop_type_id filter to the API
    const shopType = useWatch({ control, name: "shop_type_id" })
    const shopTypeId = shopType?.value

    const makeCtrl = useController({ name: "make", control })
    const modelCtrl = useController({ name: "model", control })
    const yearCtrl = useController({ name: "year", control })
    const subModelCtrl = useController({ name: "sub_model", control })
    const engineSizeCtrl = useController({ name: "engine_size", control })
    const drivetrainCtrl = useController({ name: "drivetrain", control })

    const makeValue = makeCtrl.field.value ?? ""
    const modelValue = modelCtrl.field.value ?? ""
    const yearValue = yearCtrl.field.value ?? ""

    // ── Fetch all records once (large per_page), then derive unique suggestion
    //    lists client-side so we don't invent API endpoints. ──

    type MakeAndModelRecord = {
        id?: number
        shop_type_id?: number
        make?: string
        model?: string
        year?: string
        sub_model?: string
        engine_size?: string
        drivetrain?: string
    }

    function normalizeRecord(record: unknown): MakeAndModelRecord {
        const value = record as Record<string, unknown>

        return {
            id: typeof value.id === "number" ? value.id : undefined,
            shop_type_id: typeof value.shop_type_id === "number" ? value.shop_type_id : undefined,
            make: toOptionalString(value.make),
            model: toOptionalString(value.model),
            year: toOptionalString(value.year),
            sub_model: toOptionalString(value.sub_model),
            engine_size: toOptionalString(value.engine_size),
            drivetrain: toOptionalString(value.drivetrain),
        }
    }

    function extractRecords(response: unknown): MakeAndModelRecord[] {
        const obj = response as any
        if (Array.isArray(obj?.data)) return obj.data.map(normalizeRecord)
        if (Array.isArray(obj?.data?.data)) return obj.data.data.map(normalizeRecord)
        if (Array.isArray(obj)) return obj.map(normalizeRecord)
        return []
    }

    const { data: allRecords = [], isLoading: recordsLoading } = useQuery<MakeAndModelRecord[]>({
        queryKey: ["make-and-models-all", shopTypeId],
        queryFn: async () => {
            const res = await api.makeAndModels.list({ per_page: 9999, ...(shopTypeId ? { shop_type_id: shopTypeId } : {}) })
            return extractRecords(res)
        },
        staleTime: 5 * 60 * 1000,
    })

    // Derive unique sorted lists from the full record set, filtered by upstream selections.
    const makes = unique(allRecords.map((r) => r.make))

    const models = unique(
        allRecords
            .filter((r) => !makeValue || r.make === makeValue)
            .map((r) => r.model),
    )

    const years = unique(
        allRecords
            .filter((r) => (!makeValue || r.make === makeValue) && (!modelValue || r.model === modelValue))
            .map((r) => r.year),
    )

    const subModels = unique(
        allRecords
            .filter(
                (r) =>
                    (!makeValue || r.make === makeValue) &&
                    (!modelValue || r.model === modelValue) &&
                    (!yearValue || r.year === yearValue),
            )
            .map((r) => r.sub_model),
    )

    const engineSizes = unique(
        allRecords
            .filter(
                (r) =>
                    (!makeValue || r.make === makeValue) &&
                    (!modelValue || r.model === modelValue) &&
                    (!yearValue || r.year === yearValue),
            )
            .map((r) => r.engine_size),
    )

    const drivetrains = unique(
        allRecords
            .filter(
                (r) =>
                    (!makeValue || r.make === makeValue) &&
                    (!modelValue || r.model === modelValue) &&
                    (!yearValue || r.year === yearValue),
            )
            .map((r) => r.drivetrain),
    )

    const makesLoading = recordsLoading
    const modelsLoading = false
    const yearsLoading = false
    const subModelsLoading = false
    const engineSizesLoading = false
    const drivetrainsLoading = false

    // ── Cascading onChange handlers ──

    function handleMakeChange(val: string) {
        makeCtrl.field.onChange(val)
        // Reset all downstream fields whenever make changes
        setValue("model", "")
        setValue("year", "")
        setValue("sub_model", "")
        setValue("engine_size", "")
        setValue("drivetrain", "")
    }

    function handleModelChange(val: string) {
        modelCtrl.field.onChange(val)
        setValue("year", "")
        setValue("sub_model", "")
        setValue("engine_size", "")
        setValue("drivetrain", "")
    }

    function handleYearChange(val: string) {
        yearCtrl.field.onChange(val)
        setValue("sub_model", "")
        setValue("engine_size", "")
        setValue("drivetrain", "")
    }

    return (
        <div className="space-y-4">
            <div className="grid grid-cols-1 gap-4 sm:grid-cols-3">
                <VehicleCombobox
                    label="Make"
                    placeholder="e.g. Toyota"
                    required
                    value={makeValue}
                    onChange={handleMakeChange}
                    onBlur={makeCtrl.field.onBlur}
                    options={makes}
                    loading={makesLoading}
                    error={makeCtrl.fieldState.error?.message}
                />
                <VehicleCombobox
                    label="Model"
                    placeholder="e.g. Camry"
                    required
                    value={modelValue}
                    onChange={handleModelChange}
                    onBlur={modelCtrl.field.onBlur}
                    options={models}
                    loading={modelsLoading}
                    error={modelCtrl.fieldState.error?.message}
                />
                <VehicleCombobox
                    label="Year"
                    placeholder="e.g. 2024"
                    value={yearValue}
                    onChange={handleYearChange}
                    onBlur={yearCtrl.field.onBlur}
                    options={years}
                    loading={yearsLoading}
                    error={yearCtrl.fieldState.error?.message}
                />
            </div>


            <div className="grid grid-cols-1 gap-4 sm:grid-cols-3">
            <VehicleCombobox
                label="Sub Model"
                placeholder="e.g. LE"
                value={subModelCtrl.field.value ?? ""}
                onChange={(val) => subModelCtrl.field.onChange(val)}
                onBlur={subModelCtrl.field.onBlur}
                options={subModels}
                loading={subModelsLoading}
                error={subModelCtrl.fieldState.error?.message}
            />
                <VehicleCombobox
                    label="Engine Size"
                    placeholder="e.g. 2.5L"
                    value={engineSizeCtrl.field.value ?? ""}
                    onChange={(val) => engineSizeCtrl.field.onChange(val)}
                    onBlur={engineSizeCtrl.field.onBlur}
                    options={engineSizes}
                    loading={engineSizesLoading}
                    error={engineSizeCtrl.fieldState.error?.message}
                />
                <VehicleCombobox
                    label="Drivetrain"
                    placeholder="e.g. FWD"
                    value={drivetrainCtrl.field.value ?? ""}
                    onChange={(val) => drivetrainCtrl.field.onChange(val)}
                    onBlur={drivetrainCtrl.field.onBlur}
                    options={drivetrains}
                    loading={drivetrainsLoading}
                    error={drivetrainCtrl.fieldState.error?.message}
                />
            </div>
        </div>
    )
}
