/**
 * CustomModule — runtime renderer for AI-generated modules.
 *
 * Reads the published spec at /api/ai-builder/modules and renders:
 *   • A list/table of records (data-driven columns)
 *   • A "+ Add" dialog generated from the spec.fields
 *   • Per-row Edit + Delete
 *
 * NO file generation. NO disk writes. The page is a pure interpreter of the spec.
 */
import React, { useEffect, useMemo, useState, useCallback } from "react";
import { useParams, Link, useNavigate } from "react-router-dom";
import { Card, CardContent } from "@/components/ui/card";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Badge } from "@/components/ui/badge";
import { Textarea } from "@/components/ui/textarea";
import { Switch } from "@/components/ui/switch";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter } from "@/components/ui/dialog";
import {
    Plus, Pencil, Trash2, ArrowLeft, Loader2, Bot, FileText, Sparkles,
} from "lucide-react";
import { toast } from "sonner";
import { api, formatApiError } from "@/lib/api";
import { formatINR } from "@/lib/format";

export default function CustomModule() {
    const { slug } = useParams();
    const navigate = useNavigate();
    const [spec, setSpec] = useState(null);
    const [records, setRecords] = useState([]);
    const [loading, setLoading] = useState(true);
    const [editing, setEditing] = useState(null);     // record being edited; null = new
    const [open, setOpen] = useState(false);
    const [form, setForm] = useState({});
    const [saving, setSaving] = useState(false);

    const load = useCallback(async () => {
        setLoading(true);
        try {
            const all = await api.get("/ai-builder/modules");
            const s = (all.data || []).find((m) => m.slug === slug);
            if (!s) {
                toast.error("Module not found");
                navigate("/ai-builder");
                return;
            }
            if (s.status !== "published") {
                toast.error("Module not published — go publish it first");
                navigate("/ai-builder");
                return;
            }
            setSpec(s);
            const recs = await api.get(`/ai-builder/records/${slug}`);
            setRecords(recs.data || []);
        } catch (e) { toast.error("Load failed"); }
        finally { setLoading(false); }
    }, [slug, navigate]);

    useEffect(() => { load(); }, [load]);

    const openNew = () => {
        setEditing(null);
        const blank = {};
        for (const f of spec.fields) {
            if (f.type === "switch") blank[f.key] = false;
            else if (f.type === "number" || f.type === "currency" || f.type === "percent") blank[f.key] = 0;
            else blank[f.key] = "";
        }
        setForm(blank);
        setOpen(true);
    };

    const openEdit = (rec) => {
        setEditing(rec);
        setForm({ ...rec.data });
        setOpen(true);
    };

    const submit = async () => {
        setSaving(true);
        try {
            if (editing) {
                await api.put(`/ai-builder/records/${slug}/${editing.id}`, { data: form });
                toast.success("Record updated");
            } else {
                await api.post(`/ai-builder/records/${slug}`, { data: form });
                toast.success("Record added");
            }
            setOpen(false);
            load();
        } catch (e) { toast.error(formatApiError(e.response?.data?.detail) || "Save failed"); }
        finally { setSaving(false); }
    };

    const remove = async (rec) => {
        if (!window.confirm("Delete this record?")) return;
        try {
            await api.delete(`/ai-builder/records/${slug}/${rec.id}`);
            toast.success("Deleted");
            load();
        } catch (e) { toast.error("Delete failed"); }
    };

    if (loading) return <div className="text-center text-muted-foreground py-12">Loading {slug}…</div>;
    if (!spec) return null;

    return (
        <div className="space-y-4" data-testid={`custom-module-${slug}`}>
            <div className="flex flex-wrap items-center justify-between gap-3">
                <div className="flex items-center gap-3">
                    <Button size="sm" variant="ghost" asChild>
                        <Link to="/ai-builder"><ArrowLeft className="h-4 w-4 mr-1" /> AI Builder</Link>
                    </Button>
                    <div className="rounded-xl p-2.5" style={{ background: `${spec.color || "#0C7C59"}1a`, color: spec.color || "#0C7C59" }}>
                        <Bot className="h-5 w-5" />
                    </div>
                    <div>
                        <div className="label-cap flex items-center gap-1.5"><Sparkles className="h-3 w-3" /> AI-generated · /custom/{spec.slug}</div>
                        <h1 className="font-display text-2xl md:text-3xl font-bold tracking-tight">{spec.name}</h1>
                        {spec.description && <p className="text-xs text-muted-foreground mt-0.5">{spec.description}</p>}
                    </div>
                </div>
                <Button onClick={openNew} className="bg-primary hover:bg-primary/90" data-testid="add-record-btn">
                    <Plus className="h-4 w-4 mr-1.5" /> Add {spec.name}
                </Button>
            </div>

            <Card>
                <CardContent className="p-0">
                    <div className="overflow-x-auto">
                        <table className="w-full text-sm">
                            <thead className="bg-muted/40">
                                <tr className="text-left text-[10px] uppercase tracking-wider text-muted-foreground">
                                    {spec.list_columns.map((col) => {
                                        const f = spec.fields.find((x) => x.key === col);
                                        return <th key={col} className="px-3 py-2.5">{f?.label || col}</th>;
                                    })}
                                    <th className="px-3 py-2.5 text-right">Actions</th>
                                </tr>
                            </thead>
                            <tbody>
                                {records.length === 0 ? (
                                    <tr><td colSpan={spec.list_columns.length + 1} className="p-12 text-center text-muted-foreground">
                                        <FileText className="h-8 w-8 mx-auto mb-2 opacity-40" />
                                        Koi {spec.name} record nahi hai. "Add" button se shuru karein.
                                    </td></tr>
                                ) : records.map((r) => (
                                    <tr key={r.id} className="border-t border-border hover:bg-muted/20">
                                        {spec.list_columns.map((col) => {
                                            const f = spec.fields.find((x) => x.key === col);
                                            return <td key={col} className="px-3 py-2 text-xs">{renderCell(r.data?.[col], f)}</td>;
                                        })}
                                        <td className="px-3 py-2 text-right">
                                            <Button size="sm" variant="ghost" className="h-7" onClick={() => openEdit(r)} data-testid={`edit-${r.id}`}>
                                                <Pencil className="h-3 w-3" />
                                            </Button>
                                            <Button size="sm" variant="ghost" className="h-7 text-destructive" onClick={() => remove(r)} data-testid={`del-${r.id}`}>
                                                <Trash2 className="h-3 w-3" />
                                            </Button>
                                        </td>
                                    </tr>
                                ))}
                            </tbody>
                        </table>
                    </div>
                </CardContent>
            </Card>

            {/* Dialog: add / edit */}
            <Dialog open={open} onOpenChange={setOpen}>
                <DialogContent className="max-w-2xl" data-testid="record-dialog">
                    <DialogHeader>
                        <DialogTitle>{editing ? `Edit ${spec.name}` : `Add ${spec.name}`}</DialogTitle>
                    </DialogHeader>
                    <div className="grid grid-cols-1 md:grid-cols-2 gap-3">
                        {spec.fields.map((f) => (
                            <div key={f.key} className={f.type === "textarea" ? "md:col-span-2" : ""}>
                                <Label className="text-xs">
                                    {f.label}{f.required && <span className="text-destructive ml-0.5">*</span>}
                                </Label>
                                {renderInput(f, form[f.key], (v) => setForm((s) => ({ ...s, [f.key]: v })))}
                            </div>
                        ))}
                    </div>
                    <DialogFooter className="gap-2">
                        <Button variant="outline" onClick={() => setOpen(false)}>Cancel</Button>
                        <Button onClick={submit} disabled={saving} className="bg-primary hover:bg-primary/90" data-testid="save-record-btn">
                            {saving ? <Loader2 className="h-4 w-4 animate-spin mr-1.5" /> : <Plus className="h-4 w-4 mr-1.5" />}
                            {editing ? "Update" : "Save"}
                        </Button>
                    </DialogFooter>
                </DialogContent>
            </Dialog>
        </div>
    );
}


// =============== Field renderers ===============
function renderCell(value, field) {
    if (value == null || value === "") return <span className="text-muted-foreground italic">—</span>;
    if (!field) return String(value);
    switch (field.type) {
        case "currency": return <span className="font-mono">{formatINR(Number(value) || 0)}</span>;
        case "percent": return <span className="font-mono">{value}%</span>;
        case "number": return <span className="font-mono">{value}</span>;
        case "switch": return value ? <Badge variant="default" className="text-[9px]">Yes</Badge> : <Badge variant="secondary" className="text-[9px]">No</Badge>;
        case "select":
            return <Badge variant="outline" className="text-[10px]">{value}</Badge>;
        case "date": return <span className="text-[11px]">{value}</span>;
        case "url": return <a href={value} target="_blank" rel="noopener noreferrer" className="text-primary underline truncate inline-block max-w-[200px]">{value}</a>;
        case "email": return <a href={`mailto:${value}`} className="text-primary underline">{value}</a>;
        case "phone": return <a href={`tel:${value}`} className="text-primary underline">{value}</a>;
        default: return String(value);
    }
}

function renderInput(field, value, onChange) {
    switch (field.type) {
        case "textarea":
            return <Textarea rows={3} value={value || ""} onChange={(e) => onChange(e.target.value)} placeholder={field.placeholder} className="text-sm" data-testid={`field-${field.key}`} />;
        case "number":
        case "currency":
        case "percent":
            return <Input type="number" value={value ?? 0} onChange={(e) => onChange(parseFloat(e.target.value) || 0)} placeholder={field.placeholder} className="h-9" data-testid={`field-${field.key}`} />;
        case "date":
            return <Input type="date" value={value || ""} onChange={(e) => onChange(e.target.value)} className="h-9" data-testid={`field-${field.key}`} />;
        case "datetime":
            return <Input type="datetime-local" value={value || ""} onChange={(e) => onChange(e.target.value)} className="h-9" data-testid={`field-${field.key}`} />;
        case "switch":
            return <div className="pt-2"><Switch checked={!!value} onCheckedChange={onChange} data-testid={`field-${field.key}`} /></div>;
        case "select":
            return (
                <Select value={value || ""} onValueChange={onChange}>
                    <SelectTrigger className="h-9" data-testid={`field-${field.key}`}><SelectValue placeholder={field.placeholder || "Choose…"} /></SelectTrigger>
                    <SelectContent>
                        {(field.options || []).map((opt, i) => <SelectItem key={`${opt}-${i}`} value={opt}>{opt}</SelectItem>)}
                    </SelectContent>
                </Select>
            );
        case "phone":
            return <Input type="tel" value={value || ""} onChange={(e) => onChange(e.target.value)} placeholder={field.placeholder} className="h-9" data-testid={`field-${field.key}`} />;
        case "email":
            return <Input type="email" value={value || ""} onChange={(e) => onChange(e.target.value)} placeholder={field.placeholder} className="h-9" data-testid={`field-${field.key}`} />;
        case "url":
            return <Input type="url" value={value || ""} onChange={(e) => onChange(e.target.value)} placeholder={field.placeholder} className="h-9" data-testid={`field-${field.key}`} />;
        default:
            return <Input value={value || ""} onChange={(e) => onChange(e.target.value)} placeholder={field.placeholder} className="h-9" data-testid={`field-${field.key}`} />;
    }
}
