import { useForm, router } from '@inertiajs/react';
import AppLayout from '@/layouts/AppLayout';
import { useMemo, useState } from 'react';
import { FloorPlanView, type PublicFloorPlan } from '@/components/floor-plan-view';
import { QRCardDialog } from '@/components/qr-card-dialog';
import { useTranslator } from '@/lib/i18n';
import { ExportMenu } from '@/components/export-menu';

interface Props {
    wedding: any;
    tables: any[];
    guests: any[];
    unassigned: any[];
    primary_plan?: PublicFloorPlan | null;
    share_slug?: string | null;
}

// Name for person `i` in a guest's party (0 = the named guest). #9: additional
// members use the couple-supplied name when present, falling back to the
// historical "<First> Guest N" placeholder so existing seat assignments (keyed
// by person_name) keep resolving.
function memberName(g: any, i: number): string {
    const primary = `${g.first_name} ${g.last_name ?? ''}`.trim();
    if (i === 0) return primary;
    const custom = g.party_members?.[i - 1];
    return (custom && String(custom).trim()) || `${g.first_name} Guest ${i}`;
}

export default function Seating({ wedding, tables, guests, primary_plan, share_slug }: Props) {
    const t = useTranslator();
    const [showAddTable, setShowAddTable] = useState(false);
    const [showQrCard, setShowQrCard] = useState(false);
    const [highlightTable, setHighlightTable] = useState<string | null>(null);
    // `quantity` lets the couple create N tables at once when adding a stack
    // of identical guest tables (e.g. 8 round tables with 8 seats each).
    const tableForm = useForm({ name: '', capacity: 8, shape: 'round', quantity: 1 });

    const shareUrl = share_slug && typeof window !== 'undefined'
        ? `${window.location.origin}/share/${share_slug}`
        : '';
    const eventDate = wedding.wedding_date
        ? new Date(wedding.wedding_date).toLocaleDateString('en-US', { month: 'long', day: 'numeric', year: 'numeric' })
        : undefined;

    function handleAddTable(e: React.FormEvent) {
        e.preventDefault();
        const qty = Math.max(1, Number(tableForm.data.quantity) || 1);

        // Single-table path: keep the original behavior.
        if (qty === 1) {
            tableForm.post(`/weddings/${wedding.id}/seating/tables`, {
                onSuccess: () => { tableForm.reset(); setShowAddTable(false); },
                preserveScroll: true,
            });
            return;
        }

        // Bulk path: chain POSTs auto-numbered "{baseName} 1..N". For empty
        // base name we default to "Table" so they show as Table 1..N.
        const base = (tableForm.data.name || '').trim() || 'Table';
        const existingCount = tables.length;
        let done = 0;
        for (let i = 1; i <= qty; i++) {
            const num = existingCount + i;
            router.post(`/weddings/${wedding.id}/seating/tables`, {
                name: `${base} ${num}`,
                capacity: tableForm.data.capacity,
                shape: tableForm.data.shape,
            }, {
                preserveScroll: true,
                preserveState: true,
                onFinish: () => {
                    done++;
                    if (done === qty) {
                        tableForm.reset();
                        setShowAddTable(false);
                    }
                },
            });
        }
    }

    function assignGuest(guestId: string, tableId: string | null, personName: string) {
        router.put(`/weddings/${wedding.id}/seating/seats`, {
            guest_id: guestId,
            person_name: personName,
            table_id: tableId,
        }, { preserveScroll: true });
    }

    function locateTable(name: string) {
        setHighlightTable(name);
        const anchor = document.getElementById('floor-plan-anchor');
        if (anchor) anchor.scrollIntoView({ behavior: 'smooth', block: 'start' });
    }

    // Match seating tables to floor-plan elements by label (case-insensitive trim).
    const planLabels = useMemo(() => {
        if (!primary_plan) return new Set<string>();
        return new Set(primary_plan.elements.map((el) => el.label.trim().toLowerCase()));
    }, [primary_plan]);

    const matchedTables = useMemo(
        () => tables.filter((t) => planLabels.has(t.name.trim().toLowerCase())).length,
        [tables, planLabels],
    );

    // Per-person + household seated counters. Capacity is coerced to Number because
    // the API sometimes returns it as a string, which would make `+` concatenate
    // instead of add (e.g. 6 tables × "8" → "0888888 seated").
    const totalSeats = tables.reduce((sum, t) => sum + Number(t.capacity ?? 0), 0);
    const totalSeated = tables.reduce((sum, t) => sum + ((t.seat_assignments ?? []).length), 0);

    // Expand party members into individual chips. Each chip carries a
    // compound key `guestId::personName` (same convention as wedding's drag IDs).
    type PartyMember = { id: string; guestId: string; name: string };
    const allPartyMembers: PartyMember[] = useMemo(() => {
        return guests.flatMap((g: any): PartyMember[] => {
            if (!g.party_count || g.party_count === 1) {
                const name = memberName(g, 0);
                return [{ id: `${g.id}::${name}`, guestId: g.id, name }];
            }
            return Array.from({ length: g.party_count }, (_, i): PartyMember => {
                const name = memberName(g, i);
                return { id: `${g.id}::${name}`, guestId: g.id, name };
            });
        });
    }, [guests]);

    // A person is "seated" when an assignment row links guest_id + person_name to a table.
    const seatedKeys = useMemo(() => {
        const set = new Set<string>();
        for (const t of tables) {
            for (const seat of t.seat_assignments ?? []) {
                set.add(`${seat.guest_id}::${seat.person_name}`);
            }
        }
        return set;
    }, [tables]);

    const unseated = useMemo(
        () => allPartyMembers.filter((p) => !seatedKeys.has(p.id)),
        [allPartyMembers, seatedKeys],
    );

    return (
        <AppLayout wedding={wedding}>
            <div className="max-w-6xl mx-auto px-4 sm:px-6 py-10">
                {/* Editorial header pill */}
                <div className="flex items-baseline justify-between flex-wrap gap-4 mb-10">
                    <div>
                        <p className="text-[11px] font-medium tracking-[0.22em] uppercase text-primary mb-2">
                            Reception
                        </p>
                        <h1 className="font-serif text-[2.2rem] sm:text-[2.6rem] tracking-[-0.022em] leading-[1.05]">
                            Seating plan
                            <span className="text-foreground/40"> · </span>
                            <span className="text-foreground/70">{tables.length} tables</span>
                        </h1>
                    </div>
                    <div className="flex items-center gap-3">
                        {totalSeats > 0 && (
                            <div className="inline-flex items-center gap-2 px-3 py-1.5 rounded-full bg-primary/[0.08] border border-primary/20">
                                <span className="w-1.5 h-1.5 rounded-full bg-primary animate-pulse" />
                                <span className="text-[11.5px] font-medium text-primary tracking-tight">
                                    {totalSeated} / {totalSeats} seated
                                </span>
                            </div>
                        )}
                        {share_slug && (
                            <button
                                onClick={() => setShowQrCard(true)}
                                className="btn-outline !py-2.5 !px-4 !text-[13.5px]"
                            >
                                <QrIcon className="w-4 h-4 mr-1.5" />
                                Seat-finder QR
                            </button>
                        )}
                        <ExportMenu
                            filename="seating"
                            title={t('seating.title')}
                            rows={tables}
                            columns={[
                                { header: t('seating.table_name'), value: (tbl: any) => tbl.name },
                                { header: t('seating.capacity'), value: (tbl: any) => tbl.capacity },
                                { header: t('guests.title'), value: (tbl: any) => (tbl.seat_assignments ?? []).map((a: any) => a.person_name).filter(Boolean).join(', ') },
                            ]}
                        />
                        <button
                            onClick={() => setShowAddTable(true)}
                            className="btn-charcoal !py-2.5 !px-4 !text-[13.5px]"
                        >
                            + Add table
                        </button>
                    </div>
                </div>

                {/* Unseated rail — per-person chips */}
                {tables.length > 0 && unseated.length > 0 && (
                    <div className="mb-8 bg-muted/30 border border-border rounded-2xl p-5">
                        <div className="flex items-baseline justify-between mb-3 flex-wrap gap-2">
                            <p className="text-[11px] font-medium tracking-[0.22em] uppercase text-muted-foreground">
                                Unseated · <span className="text-foreground/85">{unseated.length}</span>
                            </p>
                            <p className="text-[11px] text-muted-foreground">
                                Click a name to assign it to a table.
                            </p>
                        </div>
                        <div className="flex flex-wrap gap-1.5">
                            {unseated.map((p) => (
                                <UnseatedChip
                                    key={p.id}
                                    member={p}
                                    tables={tables}
                                    onAssign={(tableId) => assignGuest(p.guestId, tableId, p.name)}
                                />
                            ))}
                        </div>
                    </div>
                )}

                {tables.length === 0 ? (
                    <div className="text-center py-20">
                        <div className="w-14 h-14 rounded-2xl bg-muted border border-border mx-auto mb-5 flex items-center justify-center">
                            <LayoutTemplateIcon className="w-6 h-6 text-foreground/60" />
                        </div>
                        <p className="font-serif text-[1.5rem] tracking-tight mb-2">{t('seating.no_tables')}</p>
                        <p className="text-[14px] text-muted-foreground">{t('seating.add_first_table')}</p>
                    </div>
                ) : (
                    <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
                        {tables.map((table) => {
                            const assigned = table.seat_assignments ?? [];
                            const capacity = table.capacity;
                            const remaining = capacity - assigned.length;
                            const inPlan = planLabels.has(table.name.trim().toLowerCase());

                            return (
                                <div key={table.id} className="bg-card border border-border rounded-2xl p-4">
                                    <div className="flex items-center justify-between mb-3">
                                        <h3 className="font-serif text-[1.1rem] tracking-tight">{table.name}</h3>
                                        <div className="flex items-center gap-1.5">
                                            <span className="text-[11px] text-muted-foreground tabular-nums">
                                                {assigned.length}/{capacity}
                                            </span>
                                            {primary_plan && inPlan && (
                                                <button
                                                    onClick={() => locateTable(table.name)}
                                                    title={t('seating.locate_on_floorplan')}
                                                    className="p-1 rounded-md text-foreground/55 hover:text-primary hover:bg-primary/[0.08] transition-colors"
                                                >
                                                    <LayoutTemplateIcon className="w-3.5 h-3.5" />
                                                </button>
                                            )}
                                            <button
                                                onClick={() => {
                                                    if (confirm(t('seating.delete_table_confirm'))) {
                                                        router.delete(`/weddings/${wedding.id}/seating/tables/${table.id}`, { preserveScroll: true });
                                                    }
                                                }}
                                                className="p-1 rounded-md text-foreground/55 hover:text-danger transition-colors"
                                                title={t('seating.delete_table')}
                                            >
                                                <XIcon className="w-3.5 h-3.5" />
                                            </button>
                                        </div>
                                    </div>
                                    <div className="space-y-1 mb-3">
                                        {assigned.map((seat: any) => (
                                            <div key={seat.id} className="flex items-center justify-between text-[13px] bg-muted/40 rounded-md px-2.5 py-1.5">
                                                <span>{seat.person_name}</span>
                                                <button
                                                    onClick={() => assignGuest(seat.guest_id, null, seat.person_name)}
                                                    className="text-[11px] text-muted-foreground hover:text-danger transition-colors"
                                                >
                                                    {t('common.remove')}
                                                </button>
                                            </div>
                                        ))}
                                    </div>
                                    {remaining > 0 && (
                                        <div className="border border-dashed border-border rounded-lg p-2">
                                            <select
                                                className="w-full text-[12px] text-muted-foreground bg-transparent outline-none"
                                                onChange={(e) => {
                                                    const [guestId, name] = e.target.value.split('::');
                                                    if (guestId && name) assignGuest(guestId, table.id, name);
                                                    e.target.value = '';
                                                }}
                                                defaultValue=""
                                            >
                                                <option value="" disabled>{t('seating.assign_guest')}</option>
                                                {guests.flatMap((g) =>
                                                    g.party_count === 1
                                                        ? [{ id: g.id, name: memberName(g, 0) }]
                                                        : Array.from({ length: g.party_count }, (_, i) => ({
                                                            id: g.id,
                                                            name: memberName(g, i),
                                                        }))
                                                ).map((p) => (
                                                    <option key={`${p.id}::${p.name}`} value={`${p.id}::${p.name}`}>
                                                        {p.name}
                                                    </option>
                                                ))}
                                            </select>
                                        </div>
                                    )}
                                </div>
                            );
                        })}
                    </div>
                )}

                {/* Floor plan view — below tables grid */}
                {primary_plan && (
                    <section id="floor-plan-anchor" className="mt-14">
                        <div className="flex items-baseline justify-between flex-wrap gap-3 mb-5">
                            <div>
                                <p className="text-[11px] font-medium tracking-[0.22em] uppercase text-primary mb-1.5">
                                    Floor plan
                                </p>
                                <h2 className="font-serif text-[1.6rem] sm:text-[1.85rem] tracking-tight">{primary_plan.name}</h2>
                            </div>
                            <div className="flex items-center gap-3 text-[12px] text-muted-foreground">
                                <span>
                                    {matchedTables} / {tables.length} tables matched
                                </span>
                                <a
                                    href={`/weddings/${wedding.id}/floorplan`}
                                    className="text-foreground border-b border-foreground/40 hover:border-foreground transition-colors pb-0.5"
                                >
                                    Edit floor plan →
                                </a>
                            </div>
                        </div>
                        <FloorPlanView
                            plan={primary_plan}
                            highlightTable={highlightTable}
                            accent="var(--color-primary)"
                        />
                        {matchedTables < tables.length && (
                            <p className="text-[12px] text-muted-foreground mt-3">
                                Tip: tables match by name. Make sure each seating table has a matching label on the floor plan.
                            </p>
                        )}
                    </section>
                )}
            </div>

            {/* Seat-finder QR card dialog */}
            {share_slug && (
                <QRCardDialog
                    open={showQrCard}
                    onClose={() => setShowQrCard(false)}
                    url={shareUrl}
                    coupleNames={`${wedding.partner_a_name} & ${wedding.partner_b_name}`}
                    eventDate={eventDate}
                    cardType="seat"
                />
            )}

            {/* Add-table dialog */}
            {showAddTable && (
                <div className="fixed inset-0 z-50 flex items-center justify-center p-4 bg-foreground/40 backdrop-blur-sm">
                    <div className="bg-card rounded-2xl p-7 w-full max-w-sm shadow-2xl border border-border">
                        <p className="text-[11px] font-medium tracking-[0.22em] uppercase text-primary mb-3">
                            New table
                        </p>
                        <h2 className="font-serif text-[1.6rem] tracking-tight mb-5">{t('seating.add_table')}</h2>
                        <form onSubmit={handleAddTable} className="space-y-4">
                            <div>
                                <label className="block text-[12px] font-medium text-muted-foreground mb-1.5">
                                    {tableForm.data.quantity > 1 ? 'Base name (auto-numbered)' : t('seating.table_name')}
                                </label>
                                <input
                                    type="text"
                                    value={tableForm.data.name}
                                    onChange={(e) => tableForm.setData('name', e.target.value)}
                                    placeholder={tableForm.data.quantity > 1 ? 'Table  →  Table 1, Table 2, Table 3…' : 'Table 1, Sweetheart Table…'}
                                    className="input"
                                    required={tableForm.data.quantity === 1}
                                    autoFocus
                                />
                            </div>
                            <div className="grid grid-cols-3 gap-3">
                                <div>
                                    <label className="block text-[12px] font-medium text-muted-foreground mb-1.5">{t('seating.capacity')}</label>
                                    <input
                                        type="number"
                                        min={1}
                                        value={tableForm.data.capacity}
                                        onChange={(e) => tableForm.setData('capacity', Number(e.target.value))}
                                        className="input"
                                    />
                                </div>
                                <div>
                                    <label className="block text-[12px] font-medium text-muted-foreground mb-1.5">{t('seating.shape')}</label>
                                    <select
                                        value={tableForm.data.shape}
                                        onChange={(e) => tableForm.setData('shape', e.target.value)}
                                        className="input"
                                    >
                                        <option value="round">{t('seating.shape_round')}</option>
                                        <option value="rectangular">{t('seating.shape_rectangular')}</option>
                                        <option value="square">{t('seating.shape_square')}</option>
                                    </select>
                                </div>
                                <div>
                                    <label className="block text-[12px] font-medium text-muted-foreground mb-1.5" title={t('seating.quantity_help')}>
                                        {t('seating.quantity')}
                                    </label>
                                    <input
                                        type="number"
                                        min={1}
                                        max={50}
                                        value={tableForm.data.quantity}
                                        onChange={(e) => tableForm.setData('quantity', Math.max(1, Number(e.target.value) || 1))}
                                        className="input"
                                    />
                                </div>
                            </div>
                            <div className="flex gap-3 pt-2">
                                <button
                                    type="button"
                                    onClick={() => setShowAddTable(false)}
                                    className="btn-outline flex-1"
                                >
                                    {t('common.cancel')}
                                </button>
                                <button
                                    type="submit"
                                    disabled={tableForm.processing}
                                    className="btn-charcoal flex-1"
                                >
                                    {t('seating.add_table')}
                                </button>
                            </div>
                        </form>
                    </div>
                </div>
            )}
        </AppLayout>
    );
}

function UnseatedChip({
    member,
    tables,
    onAssign,
}: {
    member: { id: string; guestId: string; name: string };
    tables: any[];
    onAssign: (tableId: string) => void;
}) {
    const t = useTranslator();
    const [open, setOpen] = useState(false);
    const initials = member.name.split(' ').map((p) => p[0]).join('').slice(0, 2).toUpperCase();

    return (
        <div className="relative">
            <button
                type="button"
                onClick={() => setOpen((v) => !v)}
                className="inline-flex items-center gap-2 pl-1.5 pr-3 py-1.5 rounded-full border border-border bg-card hover:border-foreground/30 transition-colors"
            >
                <span className="w-5 h-5 rounded-full bg-primary/15 text-primary text-[9px] font-semibold flex items-center justify-center">
                    {initials}
                </span>
                <span className="text-[12.5px] text-foreground/85 tracking-tight">{member.name}</span>
            </button>
            {open && (
                <>
                    {/* Click-away */}
                    <div className="fixed inset-0 z-30" onClick={() => setOpen(false)} />
                    <div className="absolute z-40 mt-1.5 left-0 min-w-[200px] bg-card border border-border rounded-xl shadow-[0_18px_40px_-15px_rgba(0,0,0,0.18)] overflow-hidden">
                        <p className="px-3 pt-2.5 pb-1 text-[10px] tracking-[0.22em] uppercase text-muted-foreground">
                            Seat at…
                        </p>
                        {tables
                            .filter((t) => (t.seat_assignments?.length ?? 0) < t.capacity)
                            .map((t) => {
                                const free = t.capacity - (t.seat_assignments?.length ?? 0);
                                return (
                                    <button
                                        key={t.id}
                                        type="button"
                                        onClick={() => { onAssign(t.id); setOpen(false); }}
                                        className="w-full flex items-center justify-between text-left px-3 py-2 text-[13px] hover:bg-foreground/[0.04] transition-colors"
                                    >
                                        <span>{t.name}</span>
                                        <span className="text-[11px] text-muted-foreground tabular-nums">{free} free</span>
                                    </button>
                                );
                            })}
                        {tables.every((t: any) => (t.seat_assignments?.length ?? 0) >= t.capacity) && (
                            <p className="px-3 py-2 text-[12px] text-muted-foreground italic">{t('seating.all_full')}</p>
                        )}
                    </div>
                </>
            )}
        </div>
    );
}

function QrIcon({ className = '' }: { className?: string }) {
    return (
        <svg className={className} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round">
            <rect x="3" y="3" width="7" height="7" rx="1" />
            <rect x="14" y="3" width="7" height="7" rx="1" />
            <rect x="3" y="14" width="7" height="7" rx="1" />
            <path d="M14 14h3v3h-3zM20 14v3M14 20h3M20 20v1" />
        </svg>
    );
}

function LayoutTemplateIcon({ className = '' }: { className?: string }) {
    return (
        <svg className={className} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round">
            <rect x="3" y="3" width="18" height="7" rx="1.5" />
            <rect x="3" y="14" width="9" height="7" rx="1.5" />
            <rect x="14" y="14" width="7" height="7" rx="1.5" />
        </svg>
    );
}

function XIcon({ className = '' }: { className?: string }) {
    return (
        <svg className={className} viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round">
            <path d="m4 4 8 8M12 4l-8 8" />
        </svg>
    );
}
