"use client";

import { useEffect, useMemo, useState } from "react";
import { useForm } from "react-hook-form";
import { z } from "zod";
import { zodResolver } from "@hookform/resolvers/zod";

import { useToast } from "@/hooks/use-toast";

import { Input } from "@/components/ui/input";
import { Textarea } from "@/components/ui/textarea";
import { Button } from "@/components/ui/button";
import {
    Select,
    SelectTrigger,
    SelectValue,
    SelectContent,
    SelectItem,
} from "@/components/ui/select";
import {
    Card,
    CardContent,
    CardHeader,
    CardTitle,
} from "@/components/ui/card";
import { Badge } from "@/components/ui/badge";

// ─────────────────────────────────────────────────────────────
// Types
// ─────────────────────────────────────────────────────────────

type Option = { id: string | number; label: string };
type RigType = { id: number | string; name: "fiber" | "uv" | "co2_galvo" | "co2_gantry" | string };

type RigRow = {
    id: number;
    name: string;
    rig_type: number | string | null;
    rig_type_name?: string; // convenience when our API includes name
};

// ─────────────────────────────────────────────────────────────
// Helpers
// ─────────────────────────────────────────────────────────────

const RIG_TARGET_MAP: Record<string, string> = {
    fiber: "settings_fiber",
    uv: "settings_uv",
    co2_galvo: "settings_co2gal",
    co2_gantry: "settings_co2gan",
};

async function apiJson<T>(url: string, init?: RequestInit): Promise<T> {
    const res = await fetch(url, {
        ...init,
        headers: { "Content-Type": "application/json", ...(init?.headers || {}) },
                            cache: "no-store",
    });
    if (!res.ok) {
        const txt = await res.text();
        throw new Error(txt || res.statusText);
    }
    return res.json() as Promise<T>;
}

const schema = z.object({
    name: z.string().min(1, "Name is required"),
                        rig_type: z.string().min(1, "Pick a rig type"),
                        laser_source: z.string().optional().nullable(),
                        laser_software: z.string().optional().nullable(),
                        // exactly one of focus OR scan (by rig type). We let the form send nulls.
                        laser_focus_lens: z.string().optional().nullable(),
                        laser_scan_lens: z.string().optional().nullable(),
                        laser_scan_lens_apt: z.string().optional().nullable(),
                        laser_scan_lens_exp: z.string().optional().nullable(),
                        notes: z.string().optional().nullable(),
});

type FormValues = z.infer<typeof schema>;

// ─────────────────────────────────────────────────────────────
// Component
// ─────────────────────────────────────────────────────────────

export default function RigBuilderClient() {
    const { toast } = useToast();

    // Lists
    const [rigTypes, setRigTypes] = useState<RigType[]>([]);
    const [rigs, setRigs] = useState<RigRow[]>([]);

    // Options that depend on rig type
    const [sourceOpts, setSourceOpts] = useState<Option[]>([]);
    const [softwareOpts, setSoftwareOpts] = useState<Option[]>([]);
    const [scanLensOpts, setScanLensOpts] = useState<Option[]>([]);
    const [focusLensOpts, setFocusLensOpts] = useState<Option[]>([]);

    // Form
    const {
        register,
        handleSubmit,
        reset,
        setValue,
        watch,
        formState: { isSubmitting },
    } = useForm<FormValues>({
        resolver: zodResolver(schema),
                            defaultValues: {
                                name: "My Fiber #1",
                                rig_type: "",
                                laser_source: null,
                                laser_software: null,
                                laser_focus_lens: null,
                                laser_scan_lens: null,
                                laser_scan_lens_apt: null,
                                laser_scan_lens_exp: null,
                                notes: "",
                            },
    });

    const rigTypeVal = watch("rig_type");
    const rigTarget = RIG_TARGET_MAP[rigTypeVal ?? ""] || "";

    const isGantry = rigTypeVal === "co2_gantry";
    const isScan = rigTypeVal === "fiber" || rigTypeVal === "uv" || rigTypeVal === "co2_galvo";

    // Initial loads
    useEffect(() => {
        (async () => {
            try {
                const [typesRes, rigsRes] = await Promise.all([
                    apiJson<{ data: { id: number; name: string }[] }>("/api/options/user_rig_type"),
                                                              apiJson<{ data: RigRow[] }>("/api/my/rigs"),
                ]);
                setRigTypes(typesRes.data);
                setRigs(rigsRes.data);
            } catch (e: any) {
                console.warn("[rigs] initial load failed:", e?.message || e);
                toast({
                    title: "Failed to load",
                    description: "Could not load your rigs or rig types.",
                    variant: "destructive",
                });
            }
        })();
    }, [toast]);

    // Load static-ish options that depend on rig type
    useEffect(() => {
        // when rig type changes, clear type-specific fields
        setValue("laser_focus_lens", null);
        setValue("laser_scan_lens", null);
        setValue("laser_scan_lens_apt", null);
        setValue("laser_scan_lens_exp", null);

        if (!rigTarget) {
            setSourceOpts([]);
            setScanLensOpts([]);
            return;
        }

        (async () => {
            try {
                // laser sources (by target)
                const src = await apiJson<{ data: Option[] }>(`/api/options/laser_source?target=${encodeURIComponent(rigTarget)}`);
                setSourceOpts(src.data ?? []);
            } catch {
                setSourceOpts([]);
            }

            try {
                // software (generic list; if you have target-aware, swap the endpoint)
                const soft = await apiJson<{ data: Option[] }>(`/api/options/laser_software`);
                setSoftwareOpts(soft.data ?? []);
            } catch {
                setSoftwareOpts([]);
            }

            if (isScan) {
                try {
                    const lenses = await apiJson<{ data: Option[] }>(`/api/options/lens?target=${encodeURIComponent(rigTarget)}`);
                    // server already formats "110x110mm (F160)"; keep but ensure scroll
                    setScanLensOpts(lenses.data ?? []);
                } catch {
                    setScanLensOpts([]);
                }
            } else {
                setScanLensOpts([]);
            }

            if (isGantry) {
                try {
                    // focus lenses are just name strings
                    const focus = await apiJson<{ data: Option[] }>(`/api/options/laser_focus_lens`);
                    setFocusLensOpts(focus.data ?? []);
                } catch {
                    setFocusLensOpts([]);
                }
            } else {
                setFocusLensOpts([]);
            }
        })();
    }, [rigTarget, isScan, isGantry, setValue]);

    async function onSubmit(values: FormValues) {
        try {
            // shape for API
            const payload = {
                name: values.name,
                rig_type: rigTypes.find((t) => String(t.name) === String(values.rig_type))?.id ?? values.rig_type, // allow id or name
                laser_source: values.laser_source || null,
                laser_software: values.laser_software || null,
                laser_focus_lens: isGantry ? values.laser_focus_lens || null : null,
                laser_scan_lens: isScan ? values.laser_scan_lens || null : null,
                laser_scan_lens_apt: isScan ? values.laser_scan_lens_apt || null : null,
                laser_scan_lens_exp: isScan ? values.laser_scan_lens_exp || null : null,
                notes: values.notes || null,
            };

            await apiJson("/api/my/rigs", {
                method: "POST",
                body: JSON.stringify(payload),
            });

            toast({ title: "Rig saved", description: "Your rig was added." });

            // refresh list
            const rigsRes = await apiJson<{ data: RigRow[] }>("/api/my/rigs");
            setRigs(rigsRes.data);

            // keep rig type but clear the rest so it's quick to add another
            reset({
                name: "",
                rig_type: values.rig_type,
                laser_source: null,
                laser_software: null,
                laser_focus_lens: null,
                laser_scan_lens: null,
                laser_scan_lens_apt: null,
                laser_scan_lens_exp: null,
                notes: "",
            });
        } catch (e: any) {
            const message = (() => {
                try {
                    const j = JSON.parse(e?.message || "{}");
                    if (j?.errors) return `Directus error ${j.errors?.[0]?.extensions?.code || ""}: ${j.errors?.[0]?.message || "Failed"}`;
                } catch {}
                return e?.message || "Failed to save rig";
            })();

            toast({
                title: "Failed to save rig",
                description: message,
                variant: "destructive",
            });
        }
    }

    async function deleteRig(id: number) {
        if (!confirm("Delete this rig?")) return;
        try {
            await apiJson(`/api/my/rigs/${id}`, { method: "DELETE" });
            setRigs((prev) => prev.filter((r) => r.id !== id));
        } catch (e: any) {
            toast({
                title: "Delete failed",
                description: e?.message || "Could not delete rig.",
                variant: "destructive",
            });
        }
    }

    const rigTypeItems = useMemo(
        () => rigTypes.map((t) => ({ value: String(t.name), label: String(t.name).replaceAll("_", " ") })),
                                 [rigTypes]
    );

    // ─────────────────────────────────────────────────────────────
    // UI
    // ─────────────────────────────────────────────────────────────

    return (
        <div className="space-y-8">
        <Card>
        <CardHeader>
        <CardTitle>New Rig</CardTitle>
        </CardHeader>
        <CardContent>
        <form className="grid grid-cols-1 gap-6 md:grid-cols-2" onSubmit={handleSubmit(onSubmit)}>
        {/* Name */}
        <div className="space-y-2">
        <label className="text-sm font-medium">Name</label>
        <Input placeholder="e.g. My Fiber #1" {...register("name")} />
        </div>

        {/* Rig type */}
        <div className="space-y-2">
        <label className="text-sm font-medium">Rig Type</label>
        <Select
        value={rigTypeVal}
        onValueChange={(v) => setValue("rig_type", v)}
        >
        <SelectTrigger>
        <SelectValue placeholder="Choose a rig type" />
        </SelectTrigger>
        {/* add scroll so big lists are usable */}
        <SelectContent position="popper" className="max-h-64 overflow-y-auto z-50 bg-background text-foreground border">
        {rigTypeItems.map((rt) => (
            <SelectItem key={rt.value} value={rt.value}>
            {rt.label}
            </SelectItem>
        ))}
        </SelectContent>
        </Select>
        </div>

        {/* Laser Source (optional) */}
        <div className="space-y-2">
        <label className="text-sm font-medium">LASER Source</label>
        <Select
        value={watch("laser_source") ?? "none"}
        onValueChange={(v) => setValue("laser_source", v === "none" ? null : v)}
        >
        <SelectTrigger>
        <SelectValue placeholder="Optional" />
        </SelectTrigger>
        <SelectContent position="popper" className="max-h-64 overflow-y-auto z-50 bg-background text-foreground border">
        <SelectItem value="none">—</SelectItem>
        {sourceOpts.map((o) => (
            <SelectItem key={o.id} value={String(o.id)}>
            {o.label}
            </SelectItem>
        ))}
        </SelectContent>
        </Select>
        </div>

        {/* Laser Software (optional) */}
        <div className="space-y-2">
        <label className="text-sm font-medium">LASER Software</label>
        <Select
        value={watch("laser_software") ?? "none"}
        onValueChange={(v) => setValue("laser_software", v === "none" ? null : v)}
        >
        <SelectTrigger>
        <SelectValue placeholder="Optional" />
        </SelectTrigger>
        <SelectContent position="popper" className="max-h-64 overflow-y-auto z-50 bg-background text-foreground border">
        <SelectItem value="none">—</SelectItem>
        {softwareOpts.map((o) => (
            <SelectItem key={o.id} value={String(o.id)}>
            {o.label}
            </SelectItem>
        ))}
        </SelectContent>
        </Select>
        </div>

        {/* Notes spans 2 cols */}
        <div className="col-span-1 md:col-span-2 space-y-2">
        <label className="text-sm font-medium">Notes</label>
        <Textarea placeholder="Optional notes…" rows={4} {...register("notes")} />
        </div>

        {/* CONDITIONAL: Focus lens for CO2 Gantry */}
        {isGantry && (
            <div className="col-span-1 md:col-span-2 grid grid-cols-1 gap-6 md:grid-cols-2">
            <div className="space-y-2">
            <label className="text-sm font-medium">LASER Focus Lens</label>
            <Select
            value={watch("laser_focus_lens") ?? "none"}
            onValueChange={(v) => setValue("laser_focus_lens", v === "none" ? null : v)}
            >
            <SelectTrigger>
            <SelectValue placeholder="Optional" />
            </SelectTrigger>
            <SelectContent position="popper" className="max-h-64 overflow-y-auto z-50 bg-background text-foreground border">
            <SelectItem value="none">—</SelectItem>
            {focusLensOpts.map((o) => (
                <SelectItem key={o.id} value={String(o.id)}>
                {o.label}
                </SelectItem>
            ))}
            </SelectContent>
            </Select>
            </div>
            </div>
        )}

        {/* CONDITIONAL: Scan lens + accessories for fiber/uv/co2_galvo */}
        {isScan && (
            <div className="col-span-1 md:col-span-2 grid grid-cols-1 gap-6 md:grid-cols-3">
            <div className="space-y-2">
            <label className="text-sm font-medium">LASER Scan Lens</label>
            <Select
            value={watch("laser_scan_lens") ?? "none"}
            onValueChange={(v) => setValue("laser_scan_lens", v === "none" ? null : v)}
            >
            <SelectTrigger>
            <SelectValue placeholder="Optional" />
            </SelectTrigger>
            <SelectContent position="popper" className="max-h-64 overflow-y-auto z-50 bg-background text-foreground border">
            <SelectItem value="none">—</SelectItem>
            {scanLensOpts.map((o) => (
                <SelectItem key={o.id} value={String(o.id)}>
                {o.label}
                </SelectItem>
            ))}
            </SelectContent>
            </Select>
            </div>

            <div className="space-y-2">
            <label className="text-sm font-medium">Scan Lens Aperture</label>
            <Select
            value={watch("laser_scan_lens_apt") ?? "none"}
            onValueChange={(v) => setValue("laser_scan_lens_apt", v === "none" ? null : v)}
            >
            <SelectTrigger>
            <SelectValue placeholder="Optional" />
            </SelectTrigger>
            <SelectContent position="popper" className="max-h-64 overflow-y-auto z-50 bg-background text-foreground border">
            <SelectItem value="none">—</SelectItem>
            {/* These can be swapped to real options when you expose them as /api/options/... */}
            <SelectItem value="10mm">10 mm</SelectItem>
            <SelectItem value="14mm">14 mm</SelectItem>
            <SelectItem value="20mm">20 mm</SelectItem>
            <SelectItem value="30mm">30 mm</SelectItem>
            </SelectContent>
            </Select>
            </div>

            <div className="space-y-2">
            <label className="text-sm font-medium">Beam Expander</label>
            <Select
            value={watch("laser_scan_lens_exp") ?? "none"}
            onValueChange={(v) => setValue("laser_scan_lens_exp", v === "none" ? null : v)}
            >
            <SelectTrigger>
            <SelectValue placeholder="Optional" />
            </SelectTrigger>
            <SelectContent position="popper" className="max-h-64 overflow-y-auto z-50 bg-background text-foreground border">
            <SelectItem value="none">—</SelectItem>
            <SelectItem value="1.5x">1.5×</SelectItem>
            <SelectItem value="2x">2×</SelectItem>
            <SelectItem value="3x">3×</SelectItem>
            <SelectItem value="4x">4×</SelectItem>
            <SelectItem value="5x">5×</SelectItem>
            </SelectContent>
            </Select>
            </div>
            </div>
        )}

        <div className="col-span-1 md:col-span-2">
        <Button type="submit" disabled={isSubmitting}>
        {isSubmitting ? "Saving…" : "Save Rig"}
        </Button>
        </div>
        </form>
        </CardContent>
        </Card>

        {/* Existing rigs */}
        <div className="space-y-3">
        <h2 className="text-xl font-semibold">Your Rigs</h2>
        <div className="divide-y divide-border rounded-md border">
        {rigs.length === 0 && (
            <div className="p-4 text-sm opacity-70">No rigs yet.</div>
        )}
        {rigs.map((r) => (
            <div key={r.id} className="flex items-center justify-between p-4">
            <div className="flex items-center gap-3">
            <div className="font-medium">{r.name}</div>
            {r.rig_type_name && (
                <Badge variant="secondary">{r.rig_type_name}</Badge>
            )}
            </div>
            <Button variant="destructive" size="sm" onClick={() => deleteRig(r.id)}>
            Delete
            </Button>
            </div>
        ))}
        </div>
        </div>
        </div>
    );
}
