import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import {
    ArrowLeft,
    ClipboardCopy,
    ExternalLink,
    FileInput,
    Loader2,
    Plus,
    Trash2,
    GripVertical,
} from 'lucide-react';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Textarea } from '@/components/ui/textarea';
import {
    Select,
    SelectContent,
    SelectItem,
    SelectTrigger,
    SelectValue,
} from '@/components/ui/select';
import AppShell from '@/components/layout/AppShell';
import CtaFormPreview from '@/components/settings/CtaFormPreview';
import { apiFetch } from '@/lib/api';
import { buildCtaEmbedCodes } from '@/lib/ctaFormEmbed';
import { cn } from '@/lib/utils';

const FIELD_PRESETS = [
    { key: 'name', label: 'Name', type: 'text', required: true, map_to: 'name' },
    { key: 'email', label: 'Email', type: 'email', required: true, map_to: 'email' },
    {
        key: 'company_name',
        label: 'Company Name',
        type: 'text',
        required: false,
        map_to: 'company_name',
    },
    { key: 'title', label: 'Job Title', type: 'text', required: false, map_to: 'title' },
    { key: 'phone', label: 'Phone', type: 'tel', required: false, map_to: 'phone' },
    { key: 'message', label: 'Message', type: 'textarea', required: false, map_to: 'message' },
];

const MAP_OPTIONS = [
    { value: 'name', label: 'Full name' },
    { value: 'email', label: 'Email' },
    { value: 'company_name', label: 'Company' },
    { value: 'title', label: 'Job title' },
    { value: 'phone', label: 'Phone' },
    { value: 'message', label: 'Message' },
    { value: 'custom', label: 'Custom (in submission only)' },
];

const AUTOSAVE_MS = 600;

function emptyDraft() {
    return {
        name: 'New contact form',
        fields: FIELD_PRESETS.slice(0, 3).map((f) => ({ ...f })),
    };
}

function draftFromForm(form) {
    return {
        name: form.name,
        fields: (form.fields || []).map((f) => ({ ...f })),
    };
}

function draftSnapshot(draft) {
    return JSON.stringify({
        name: (draft.name || '').trim(),
        fields: draft.fields || [],
    });
}

function CopyBlock({ label, code }) {
    return (
        <div className="space-y-2">
            <div className="flex items-center justify-between gap-2">
                <p className="text-xs font-medium text-slate-600">{label}</p>
                <Button
                    type="button"
                    variant="outline"
                    size="sm"
                    className="h-7 gap-1 text-xs"
                    disabled={!code}
                    onClick={() => code && navigator.clipboard.writeText(code)}
                >
                    <ClipboardCopy className="h-3 w-3" />
                    Copy
                </Button>
            </div>
            <Textarea
                readOnly
                value={code || ''}
                rows={3}
                className="text-xs font-mono h-auto min-h-[4.5rem]"
            />
        </div>
    );
}

function SaveIndicator({ state }) {
    if (state === 'saving') {
        return (
            <span className="inline-flex items-center gap-1.5 text-xs text-slate-500">
                <Loader2 className="h-3 w-3 animate-spin" />
                Saving…
            </span>
        );
    }
    if (state === 'saved') {
        return <span className="text-xs text-green-600">Saved</span>;
    }
    if (state === 'error') {
        return <span className="text-xs text-red-600">Could not save</span>;
    }
    return null;
}

export default function CtaFormsSettings({ onBack }) {
    const [forms, setForms] = useState([]);
    const [loading, setLoading] = useState(true);
    const [selectedId, setSelectedId] = useState(null);
    const [draft, setDraft] = useState(emptyDraft());
    const [saveState, setSaveState] = useState('idle');
    const [creating, setCreating] = useState(false);
    const [error, setError] = useState('');

    const skipAutosaveRef = useRef(true);
    const saveTimerRef = useRef(null);
    const lastSavedSnapshotRef = useRef('');
    const savedFadeTimerRef = useRef(null);
    const dragFieldIdxRef = useRef(null);
    const [dropFieldIdx, setDropFieldIdx] = useState(null);

    const selected = useMemo(
        () => forms.find((f) => f.id === selectedId) || null,
        [forms, selectedId]
    );

    const embedCodes = useMemo(() => {
        if (!selected?.public_id) {
            return { embed_iframe: '', embed_script: '' };
        }
        return buildCtaEmbedCodes({
            publicId: selected.public_id,
            name: draft.name,
        });
    }, [selected?.public_id, draft.name]);

    const previewUrl = selected?.public_id ? `/embed/cta/${selected.public_id}` : '';

    const loadForms = useCallback(async () => {
        setLoading(true);
        setError('');
        try {
            const r = await apiFetch('/api/cta-forms');
            const data = r.ok ? await r.json() : { forms: [] };
            if (!r.ok) throw new Error(data.detail || 'Could not load forms');
            const list = data.forms || [];
            setForms(list);
            setSelectedId((prev) => {
                if (prev && list.some((f) => f.id === prev)) return prev;
                return list.length ? list[0].id : null;
            });
        } catch (e) {
            setError(e.message || 'Load failed');
            setForms([]);
        } finally {
            setLoading(false);
        }
    }, []);

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

    useEffect(() => {
        if (!selected) return;
        const next = draftFromForm(selected);
        skipAutosaveRef.current = true;
        lastSavedSnapshotRef.current = draftSnapshot(next);
        setDraft(next);
        setSaveState('idle');
    }, [selected?.id]);

    useEffect(() => {
        if (!selectedId) return;
        if (skipAutosaveRef.current) {
            skipAutosaveRef.current = false;
            return;
        }

        const snapshot = draftSnapshot(draft);
        if (snapshot === lastSavedSnapshotRef.current) return;

        const name = draft.name?.trim();
        if (!name) return;

        if (saveTimerRef.current) clearTimeout(saveTimerRef.current);
        saveTimerRef.current = setTimeout(async () => {
            const payload = JSON.parse(snapshot);
            if (payload.name !== (draft.name || '').trim()) return;
            if (snapshot !== draftSnapshot(draft)) return;

            setSaveState('saving');
            try {
                const res = await apiFetch(`/api/cta-forms/${selectedId}`, {
                    method: 'PATCH',
                    headers: { 'Content-Type': 'application/json' },
                    body: JSON.stringify({
                        name: payload.name,
                        fields: payload.fields,
                    }),
                });
                const data = await res.json();
                if (!res.ok) throw new Error(data.detail || 'Save failed');
                lastSavedSnapshotRef.current = snapshot;
                setForms((prev) => prev.map((f) => (f.id === data.id ? data : f)));
                if (savedFadeTimerRef.current) clearTimeout(savedFadeTimerRef.current);
                setSaveState('saved');
                savedFadeTimerRef.current = window.setTimeout(() => setSaveState('idle'), 2000);
            } catch (e) {
                setError(e.message || 'Save failed');
                setSaveState('error');
            }
        }, AUTOSAVE_MS);

        return () => {
            if (saveTimerRef.current) clearTimeout(saveTimerRef.current);
        };
    }, [draft, selectedId]);

    const selectForm = (f) => {
        const next = draftFromForm(f);
        setSelectedId(f.id);
        skipAutosaveRef.current = true;
        lastSavedSnapshotRef.current = draftSnapshot(next);
        setDraft(next);
        setSaveState('idle');
    };

    const createForm = async () => {
        setCreating(true);
        setError('');
        try {
            const res = await apiFetch('/api/cta-forms', {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({
                    name: 'New contact form',
                    fields: FIELD_PRESETS.slice(0, 3),
                }),
            });
            const data = await res.json();
            if (!res.ok) throw new Error(data.detail || 'Create failed');
            await loadForms();
            setSelectedId(data.id);
            const next = draftFromForm(data);
            skipAutosaveRef.current = true;
            lastSavedSnapshotRef.current = draftSnapshot(next);
            setDraft(next);
        } catch (e) {
            setError(e.message || 'Create failed');
        } finally {
            setCreating(false);
        }
    };

    const deleteForm = async () => {
        if (!selectedId) return;
        if (!window.confirm('Delete this form? Embed codes will stop working.')) return;
        try {
            const res = await apiFetch(`/api/cta-forms/${selectedId}`, { method: 'DELETE' });
            if (!res.ok) {
                const data = await res.json().catch(() => ({}));
                throw new Error(data.detail || 'Delete failed');
            }
            setSelectedId(null);
            setDraft(emptyDraft());
            await loadForms();
        } catch (e) {
            setError(e.message || 'Delete failed');
        }
    };

    const addPreset = (preset) => {
        setDraft((d) => {
            const keys = new Set(d.fields.map((f) => f.key));
            let key = preset.key;
            let n = 2;
            while (keys.has(key)) {
                key = `${preset.key}_${n}`;
                n += 1;
            }
            return {
                ...d,
                fields: [...d.fields, { ...preset, key }],
            };
        });
    };

    const updateField = (idx, patch) => {
        setDraft((d) => ({
            ...d,
            fields: d.fields.map((f, i) => (i === idx ? { ...f, ...patch } : f)),
        }));
    };

    const removeField = (idx) => {
        setDraft((d) => ({
            ...d,
            fields: d.fields.filter((_, i) => i !== idx),
        }));
    };

    const reorderFields = (fromIdx, toIdx) => {
        if (fromIdx === toIdx || fromIdx == null || toIdx == null) return;
        setDraft((d) => {
            const fields = [...d.fields];
            const [moved] = fields.splice(fromIdx, 1);
            fields.splice(toIdx, 0, moved);
            return { ...d, fields };
        });
    };

    const onFieldDragStart = (idx) => (e) => {
        dragFieldIdxRef.current = idx;
        e.dataTransfer.effectAllowed = 'move';
        e.dataTransfer.setData('text/plain', String(idx));
    };

    const onFieldDragOver = (idx) => (e) => {
        e.preventDefault();
        e.dataTransfer.dropEffect = 'move';
        setDropFieldIdx(idx);
    };

    const onFieldDrop = (idx) => (e) => {
        e.preventDefault();
        const fromIdx = Number(e.dataTransfer.getData('text/plain'));
        reorderFields(fromIdx, idx);
        dragFieldIdxRef.current = null;
        setDropFieldIdx(null);
    };

    const onFieldDragEnd = () => {
        dragFieldIdxRef.current = null;
        setDropFieldIdx(null);
    };

    return (
        <AppShell
            title="CTA Forms"
            subtitle="Build embeddable lead forms for your website. Submissions appear in Leads."
        >
            <div className="w-full max-w-7xl">
                <div className="mb-6 flex flex-wrap items-center gap-3">
                    <Button type="button" variant="outline" className="gap-2" onClick={onBack}>
                        <ArrowLeft className="h-4 w-4" aria-hidden />
                        Back to settings
                    </Button>
                    <Button type="button" onClick={createForm} disabled={creating} className="gap-2">
                        {creating ? (
                            <Loader2 className="h-4 w-4 animate-spin" />
                        ) : (
                            <Plus className="h-4 w-4" />
                        )}
                        New form
                    </Button>
                </div>

                {error ? (
                    <p className="mb-4 text-sm text-red-600 rounded-lg border border-red-200 bg-red-50 px-3 py-2">
                        {error}
                    </p>
                ) : null}

                {loading ? (
                    <div className="flex justify-center py-20 text-slate-400">
                        <Loader2 className="h-10 w-10 animate-spin" />
                    </div>
                ) : (
                    <div className="grid gap-6 lg:grid-cols-[220px_minmax(0,1fr)] xl:grid-cols-[220px_minmax(0,1fr)_300px]">
                        <aside className="rounded-2xl border border-slate-200 bg-white p-3 shadow-sm h-fit">
                            <p className="px-2 py-1 text-xs font-semibold uppercase tracking-wide text-slate-500">
                                Your forms
                            </p>
                            {forms.length === 0 ? (
                                <p className="px-2 py-4 text-sm text-slate-500">
                                    No forms yet. Create one to get embed codes.
                                </p>
                            ) : (
                                <ul className="space-y-1">
                                    {forms.map((f) => (
                                        <li key={f.id}>
                                            <button
                                                type="button"
                                                onClick={() => selectForm(f)}
                                                className={cn(
                                                    'w-full rounded-lg px-3 py-2 text-left text-sm transition-colors',
                                                    selectedId === f.id
                                                        ? 'bg-violet-100 text-violet-800 font-medium'
                                                        : 'text-slate-700 hover:bg-slate-50'
                                                )}
                                            >
                                                {f.name || 'Untitled'}
                                            </button>
                                        </li>
                                    ))}
                                </ul>
                            )}
                        </aside>

                        <div className="space-y-6 min-w-0">
                            {!selected ? (
                                <div className="rounded-2xl border border-dashed border-slate-200 bg-white p-10 text-center text-slate-500">
                                    Create a form to configure fields and copy embed codes for WordPress.
                                </div>
                            ) : (
                                <>
                                    <section className="rounded-2xl border border-slate-200 bg-white p-6 shadow-sm space-y-4">
                                        <div className="flex flex-wrap items-end gap-3 justify-between">
                                            <div className="flex-1 min-w-[12rem]">
                                                <label className="text-xs font-medium text-slate-600">
                                                    Form name
                                                </label>
                                                <p className="text-[10px] text-slate-400 mt-0.5">
                                                    Internal label only — not shown on the embed
                                                </p>
                                                <Input
                                                    value={draft.name}
                                                    onChange={(e) =>
                                                        setDraft((d) => ({
                                                            ...d,
                                                            name: e.target.value,
                                                        }))
                                                    }
                                                    className="mt-1"
                                                />
                                            </div>
                                            <div className="flex items-center gap-3 pb-1">
                                                <SaveIndicator state={saveState} />
                                                <Button
                                                    type="button"
                                                    variant="outline"
                                                    size="sm"
                                                    className="text-red-600"
                                                    onClick={deleteForm}
                                                >
                                                    <Trash2 className="h-4 w-4" />
                                                </Button>
                                            </div>
                                        </div>

                                        <div>
                                            <p className="text-xs font-medium text-slate-600 mb-2">
                                                Add field
                                            </p>
                                            <div className="flex flex-wrap gap-2">
                                                {FIELD_PRESETS.map((p) => (
                                                    <Button
                                                        key={p.key}
                                                        type="button"
                                                        variant="outline"
                                                        size="sm"
                                                        onClick={() => addPreset(p)}
                                                    >
                                                        + {p.label}
                                                    </Button>
                                                ))}
                                            </div>
                                        </div>

                                        <div className="space-y-3">
                                            <p className="text-xs font-semibold uppercase tracking-wide text-slate-500">
                                                Fields
                                            </p>
                                            {draft.fields.length > 1 ? (
                                                <p className="text-[10px] text-slate-400">
                                                    Drag the handle to reorder fields
                                                </p>
                                            ) : null}
                                            {draft.fields.length === 0 ? (
                                                <p className="text-sm text-slate-500">
                                                    Add at least Name and Email.
                                                </p>
                                            ) : (
                                                draft.fields.map((f, idx) => (
                                                    <div
                                                        key={f.key}
                                                        onDragOver={onFieldDragOver(idx)}
                                                        onDrop={onFieldDrop(idx)}
                                                        onDragEnd={onFieldDragEnd}
                                                        className={cn(
                                                            'flex flex-wrap gap-2 items-end rounded-xl border bg-slate-50/80 p-3 transition-colors',
                                                            dropFieldIdx === idx
                                                                ? 'border-violet-300 bg-violet-50/60'
                                                                : 'border-slate-100'
                                                        )}
                                                    >
                                                        <button
                                                            type="button"
                                                            draggable
                                                            onDragStart={onFieldDragStart(idx)}
                                                            onDragEnd={onFieldDragEnd}
                                                            className="mb-2.5 shrink-0 cursor-grab rounded p-0.5 text-slate-300 hover:text-slate-500 active:cursor-grabbing"
                                                            aria-label={`Drag to reorder ${f.label}`}
                                                        >
                                                            <GripVertical className="h-4 w-4" />
                                                        </button>
                                                        <div className="flex-1 min-w-[8rem]">
                                                            <label className="text-[10px] text-slate-500">
                                                                Label
                                                            </label>
                                                            <Input
                                                                value={f.label}
                                                                onChange={(e) =>
                                                                    updateField(idx, {
                                                                        label: e.target.value,
                                                                    })
                                                                }
                                                                className="h-9 text-sm"
                                                            />
                                                        </div>
                                                        <div className="w-28">
                                                            <label className="text-[10px] text-slate-500">
                                                                Type
                                                            </label>
                                                            <Select
                                                                value={f.type}
                                                                onValueChange={(v) =>
                                                                    updateField(idx, { type: v })
                                                                }
                                                            >
                                                                <SelectTrigger className="h-9 text-sm">
                                                                    <SelectValue />
                                                                </SelectTrigger>
                                                                <SelectContent>
                                                                    <SelectItem value="text">
                                                                        Text
                                                                    </SelectItem>
                                                                    <SelectItem value="email">
                                                                        Email
                                                                    </SelectItem>
                                                                    <SelectItem value="tel">
                                                                        Phone
                                                                    </SelectItem>
                                                                    <SelectItem value="textarea">
                                                                        Long text
                                                                    </SelectItem>
                                                                </SelectContent>
                                                            </Select>
                                                        </div>
                                                        <div className="w-36">
                                                            <label className="text-[10px] text-slate-500">
                                                                Maps to lead
                                                            </label>
                                                            <Select
                                                                value={f.map_to}
                                                                onValueChange={(v) =>
                                                                    updateField(idx, { map_to: v })
                                                                }
                                                            >
                                                                <SelectTrigger className="h-9 text-sm">
                                                                    <SelectValue />
                                                                </SelectTrigger>
                                                                <SelectContent>
                                                                    {MAP_OPTIONS.map((o) => (
                                                                        <SelectItem
                                                                            key={o.value}
                                                                            value={o.value}
                                                                        >
                                                                            {o.label}
                                                                        </SelectItem>
                                                                    ))}
                                                                </SelectContent>
                                                            </Select>
                                                        </div>
                                                        <label className="flex items-center gap-1.5 text-xs text-slate-600 pb-2">
                                                            <input
                                                                type="checkbox"
                                                                checked={!!f.required}
                                                                onChange={(e) =>
                                                                    updateField(idx, {
                                                                        required: e.target.checked,
                                                                    })
                                                                }
                                                            />
                                                            Required
                                                        </label>
                                                        <Button
                                                            type="button"
                                                            variant="ghost"
                                                            size="icon"
                                                            className="h-9 w-9 text-red-500"
                                                            onClick={() => removeField(idx)}
                                                        >
                                                            <Trash2 className="h-4 w-4" />
                                                        </Button>
                                                    </div>
                                                ))
                                            )}
                                        </div>
                                    </section>

                                    <section className="rounded-2xl border border-slate-200 bg-white p-6 shadow-sm space-y-4 xl:hidden">
                                        <PreviewPanel draft={draft} previewUrl={previewUrl} />
                                    </section>

                                    <section className="rounded-2xl border border-slate-200 bg-white p-6 shadow-sm space-y-4">
                                        <div className="flex items-center gap-2 text-slate-800 font-semibold">
                                            <FileInput className="h-5 w-5 text-violet-600" />
                                            Embed on WordPress
                                        </div>
                                        <p className="text-sm text-slate-600">
                                            Paste either code into a WordPress HTML block, page builder, or
                                            theme widget. The form sizes itself to fit your page width.
                                            Submissions go straight to <strong>Leads</strong> in this workspace.
                                        </p>

                                        <CopyBlock
                                            label="Iframe embed (recommended)"
                                            code={embedCodes.embed_iframe}
                                        />
                                        <CopyBlock label="Script embed" code={embedCodes.embed_script} />
                                        {previewUrl ? (
                                            <p className="text-xs text-slate-500">
                                                Full-page preview:{' '}
                                                <a
                                                    href={previewUrl}
                                                    target="_blank"
                                                    rel="noreferrer"
                                                    className="inline-flex items-center gap-1 text-violet-600 underline"
                                                >
                                                    Open in new tab
                                                    <ExternalLink className="h-3 w-3" />
                                                </a>
                                            </p>
                                        ) : null}
                                    </section>
                                </>
                            )}
                        </div>

                        {selected ? (
                            <aside className="hidden xl:block">
                                <div className="sticky top-4 rounded-2xl border border-slate-200 bg-white p-4 shadow-sm">
                                    <PreviewPanel draft={draft} previewUrl={previewUrl} />
                                </div>
                            </aside>
                        ) : null}
                    </div>
                )}
            </div>
        </AppShell>
    );
}

function PreviewPanel({ draft, previewUrl }) {
    return (
        <div className="space-y-3">
            <div className="flex items-center justify-between gap-2">
                <p className="text-sm font-semibold text-slate-800">Live preview</p>
                {previewUrl ? (
                    <a
                        href={previewUrl}
                        target="_blank"
                        rel="noreferrer"
                        className="inline-flex items-center gap-1 text-xs text-violet-600 hover:underline"
                    >
                        Open tab
                        <ExternalLink className="h-3 w-3" />
                    </a>
                ) : null}
            </div>
            <div className="overflow-hidden rounded-xl border border-slate-200 bg-slate-50 p-1">
                <CtaFormPreview fields={draft.fields} className="border-0 shadow-none w-full" />
            </div>
            <p className="text-[10px] text-slate-400 text-center">
                Updates as you edit · matches embed appearance
            </p>
        </div>
    );
}
