import { Link, router, useForm } from '@inertiajs/react';
import { ArrowRightCircle, Ban, Download, FileText, Inbox, Plus, RotateCcw, Search, Settings2 } from 'lucide-react';
import { useState } from 'react';
import { CopyText } from '@/components/CopyText';
import { PageHeader } from '@/components/PageHeader';
import { Pagination } from '@/components/Pagination';
import { Badge } from '@/components/ui/badge';
import { Button } from '@/components/ui/button';
import { Card } from '@/components/ui/card';
import { Dialog } from '@/components/ui/dialog';
import { Input, Select, Textarea } from '@/components/ui/input';
import { Field } from '@/components/ui/label';
import { Table, Td, Th } from '@/components/ui/table';
import AppLayout from '@/layouts/AppLayout';
import { ago, dateTime, money } from '@/lib/format';
import { cn } from '@/lib/utils';
import type { Paginated } from '@/types';

type Lead = {
    id: number; status: 'open' | 'converted' | 'dismissed'; name: string; email: string; phone: string | null; company_name: string | null; address: string | null;
    message: string; source: string; estimated_value_cents: number | null; owner_id: number | null; owner: string | null; notes: string | null;
    files: { name: string; size: number; url: string }[]; quote: { id: number; number: string; status: string } | null; created_at: string; page_url: string | null;
};
type Props = {
    leads: Paginated<Lead>; filters: { status: string; q: string | null }; counts: Record<string, number>;
    owners: { id: number; name: string }[]; templates: { id: number; name: string }[];
    canEdit: boolean; showMoney: boolean; selected: number | null; formUrl: string; canSettings: boolean;
};

const TABS = [['open', 'Open'], ['converted', 'Converted'], ['dismissed', 'Dismissed'], ['all', 'All']] as const;
const STATUS_CLS: Record<string, string> = { open: 'bg-blue/10 text-[#0b56b0]', converted: 'bg-teal/10 text-[#05705f]', dismissed: 'bg-stone-100 text-stone-700' };

export default function LeadsIndex(props: Props) {
    const { leads, filters, counts, canEdit, showMoney } = props;
    const [q, setQ] = useState(filters.q ?? '');
    const [openId, setOpenId] = useState<number | null>(props.selected);
    const [adding, setAdding] = useState(false);
    const current = leads.data.find((l) => l.id === openId) ?? null;
    const go = (patch: Record<string, string | null>) => router.get('/leads', Object.fromEntries(Object.entries({ status: filters.status, q: q || null, ...patch }).filter(([, v]) => v)), { preserveState: true, replace: true });
    const total = Object.values(counts).reduce((a, b) => a + b, 0);

    return (
        <AppLayout title="Leads">
            <PageHeader title="Leads" description="Enquiries from your lead form. Give each an owner and value, then convert it to a draft quote or dismiss it."
                actions={<>
                    {props.canSettings && <Button variant="secondary" asChild><Link href="/leads/form" data-testid="lead-form-settings"><Settings2 className="h-4 w-4" /> Lead form</Link></Button>}
                    {canEdit && <Button onClick={() => setAdding(true)} data-testid="add-lead"><Plus className="h-4 w-4" /> Add lead</Button>}
                </>} />
            <Card className="mb-4 flex flex-wrap items-center gap-3 p-3">
                <div className="flex flex-wrap gap-1" role="tablist">
                    {TABS.map(([k, label]) => (
                        <button key={k} role="tab" aria-selected={filters.status === k} onClick={() => go({ status: k })} data-testid={`leads-tab-${k}`}
                            className={cn('rounded-[5px] px-3 py-1.5 text-sm font-medium', filters.status === k ? 'bg-accent-fill text-accent-ink' : 'hover:bg-accent-soft')}>
                            {label} <span className="ml-1 text-xs opacity-75">{k === 'all' ? total : counts[k] ?? 0}</span>
                        </button>
                    ))}
                </div>
                <form className="ml-auto flex items-center gap-2" onSubmit={(e) => { e.preventDefault(); go({ q: q || null }); }}>
                    <Input value={q} onChange={(e) => setQ(e.target.value)} placeholder="Search name, email, message" aria-label="Search leads" className="w-64" />
                    <Button variant="secondary" size="icon" aria-label="Search"><Search className="h-4 w-4" /></Button>
                </form>
            </Card>
            <Card>
                {leads.data.length === 0 ? (
                    <div className="px-6 py-14 text-center text-sm text-ink-muted" data-testid="leads-empty">
                        <Inbox className="mx-auto mb-3 h-8 w-8 opacity-50" />
                        No {filters.status === 'all' ? '' : filters.status} leads{filters.q ? ' match your search' : ''}. Share your lead form to start collecting enquiries:
                        <div className="mx-auto mt-3 max-w-md"><CopyText value={props.formUrl} /></div>
                    </div>
                ) : (
                    <Table>
                        <thead><tr><Th>Received</Th><Th>From</Th><Th>Message</Th>{showMoney && <Th className="text-right">Est. value</Th>}<Th>Owner</Th><Th>Status</Th></tr></thead>
                        <tbody>
                            {leads.data.map((l) => (
                                <tr key={l.id} className="cursor-pointer hover:bg-stone-50" onClick={() => setOpenId(l.id)} data-testid="lead-row">
                                    <Td className="whitespace-nowrap text-ink-muted" title={dateTime(l.created_at)}>{ago(l.created_at)}</Td>
                                    <Td><div className="font-medium">{l.name}</div><div className="text-xs text-ink-muted">{l.company_name ?? l.email}</div></Td>
                                    <Td className="max-w-md"><span className="line-clamp-2 text-sm">{l.message}</span></Td>
                                    {showMoney && <Td className="whitespace-nowrap text-right">{l.estimated_value_cents != null ? money(l.estimated_value_cents) : '—'}</Td>}
                                    <Td className="whitespace-nowrap">{l.owner ?? <span className="text-ink-muted">Unassigned</span>}</Td>
                                    <Td><Badge className={STATUS_CLS[l.status]}>{l.status === 'converted' && l.quote ? `Converted · ${l.quote.number}` : l.status[0].toUpperCase() + l.status.slice(1)}</Badge></Td>
                                </tr>
                            ))}
                        </tbody>
                    </Table>
                )}
                <Pagination page={leads} />
            </Card>
            {current && <LeadDialog key={current.id} lead={current} {...props} onClose={() => setOpenId(null)} />}
            <AddLead open={adding} onClose={() => setAdding(false)} />
        </AppLayout>
    );
}

function LeadDialog({ lead, owners, templates, canEdit, showMoney, onClose }: Props & { lead: Lead; onClose: () => void }) {
    const form = useForm({
        estimated_value: lead.estimated_value_cents != null ? (lead.estimated_value_cents / 100).toFixed(2) : '',
        owner_id: lead.owner_id ? String(lead.owner_id) : '',
        notes: lead.notes ?? '',
    });
    const [template, setTemplate] = useState('');
    const [converting, setConverting] = useState(false);
    const save = () => {
        form.transform((d) => ({ ...d, estimated_value: d.estimated_value === '' ? null : d.estimated_value, owner_id: d.owner_id ? Number(d.owner_id) : null }));
        form.put(`/leads/${lead.id}`, { preserveScroll: true, preserveState: true });
    };
    const setStatus = (status: 'open' | 'dismissed') => router.put(`/leads/${lead.id}`, { status }, { preserveScroll: true, onSuccess: onClose });
    const convert = () => { setConverting(true); router.post(`/leads/${lead.id}/convert`, { template_id: template ? Number(template) : null }, { onFinish: () => setConverting(false) }); };
    const editable = canEdit && lead.status !== 'converted';

    return (
        <Dialog open onOpenChange={(o) => !o && onClose()} title={lead.name} description={`${lead.source === 'manual' ? 'Added by hand' : 'Lead form'} · ${dateTime(lead.created_at)}`} size="xl">
            <div className="grid gap-5 md:grid-cols-[1fr_16rem]" data-testid="lead-dialog">
                <div className="min-w-0 space-y-4">
                    <dl className="grid grid-cols-[6rem_1fr] gap-x-3 gap-y-1 text-sm">
                        <dt className="text-ink-muted">Email</dt><dd><a href={`mailto:${lead.email}`} className="text-link underline">{lead.email}</a></dd>
                        {lead.phone && <><dt className="text-ink-muted">Phone</dt><dd><a href={`tel:${lead.phone.replace(/[^\d+]/g, '')}`} className="text-link underline">{lead.phone}</a></dd></>}
                        {lead.company_name && <><dt className="text-ink-muted">Company</dt><dd>{lead.company_name}</dd></>}
                        {lead.address && <><dt className="text-ink-muted">Address</dt><dd>{lead.address}</dd></>}
                        {lead.page_url && <><dt className="text-ink-muted">From page</dt><dd className="truncate text-ink-muted">{lead.page_url}</dd></>}
                    </dl>
                    <div className="whitespace-pre-wrap rounded-md bg-stone-50 p-3 text-sm" data-testid="lead-message">{lead.message}</div>
                    {lead.files.length > 0 && (
                        <ul className="space-y-1 text-sm">{lead.files.map((f) => (
                            <li key={f.url}><a href={f.url} className="inline-flex items-center gap-1.5 text-link underline"><Download className="h-3.5 w-3.5" /> {f.name}</a> <span className="text-xs text-ink-muted">({Math.ceil(f.size / 1024)} KB)</span></li>
                        ))}</ul>
                    )}
                    <Field label="Notes" htmlFor="lead-notes" error={form.errors.notes}>
                        <Textarea id="lead-notes" rows={3} value={form.data.notes} disabled={!canEdit} onChange={(e) => form.setData('notes', e.target.value)} />
                    </Field>
                </div>
                <div className="space-y-4">
                    {showMoney && (
                        <Field label="Estimated value (AUD)" htmlFor="lead-value" error={form.errors.estimated_value}>
                            <Input id="lead-value" inputMode="decimal" value={form.data.estimated_value} disabled={!canEdit} onChange={(e) => form.setData('estimated_value', e.target.value.replace(/[^\d.]/g, ''))} placeholder="0.00" />
                        </Field>
                    )}
                    <Field label="Owner" htmlFor="lead-owner" error={form.errors.owner_id}>
                        <Select id="lead-owner" value={form.data.owner_id} disabled={!canEdit} onChange={(e) => form.setData('owner_id', e.target.value)}>
                            <option value="">Unassigned</option>
                            {owners.map((o) => <option key={o.id} value={o.id}>{o.name}</option>)}
                        </Select>
                    </Field>
                    {canEdit && <Button variant="secondary" className="w-full" onClick={save} disabled={form.processing || !form.isDirty} data-testid="lead-save">Save</Button>}
                    <hr className="border-line" />
                    {lead.quote ? (
                        <Button asChild className="w-full"><Link href={`/quotes/${lead.quote.id}/edit`}><FileText className="h-4 w-4" /> Open {lead.quote.number}</Link></Button>
                    ) : editable && (
                        <div className="space-y-2">
                            <Field label="Template (optional)" htmlFor="lead-template">
                                <Select id="lead-template" value={template} onChange={(e) => setTemplate(e.target.value)}>
                                    <option value="">Blank quote</option>
                                    {templates.map((t) => <option key={t.id} value={t.id}>{t.name}</option>)}
                                </Select>
                            </Field>
                            <Button className="w-full" onClick={convert} disabled={converting} data-testid="lead-convert"><ArrowRightCircle className="h-4 w-4" /> Convert to draft quote</Button>
                            <p className="text-xs text-ink-muted">The contact is matched by email (or created) and filled in on the quote.</p>
                        </div>
                    )}
                    {canEdit && lead.status === 'open' && <Button variant="ghost" className="w-full" onClick={() => setStatus('dismissed')} data-testid="lead-dismiss"><Ban className="h-4 w-4" /> Dismiss</Button>}
                    {canEdit && lead.status === 'dismissed' && <Button variant="ghost" className="w-full" onClick={() => setStatus('open')}><RotateCcw className="h-4 w-4" /> Reopen</Button>}
                </div>
            </div>
        </Dialog>
    );
}

function AddLead({ open, onClose }: { open: boolean; onClose: () => void }) {
    const form = useForm({ name: '', email: '', phone: '', company_name: '', message: '' });
    const submit = (e: React.FormEvent) => { e.preventDefault(); form.post('/leads', { onSuccess: () => { form.reset(); onClose(); } }); };
    return (
        <Dialog open={open} onOpenChange={(o) => !o && onClose()} title="Add a lead" description="For enquiries by phone or email.">
            <form onSubmit={submit} className="grid gap-3">
                <div className="grid gap-3 sm:grid-cols-2">
                    <Field label="Name" htmlFor="al-name" error={form.errors.name}><Input id="al-name" value={form.data.name} onChange={(e) => form.setData('name', e.target.value)} required /></Field>
                    <Field label="Email" htmlFor="al-email" error={form.errors.email}><Input id="al-email" type="email" value={form.data.email} onChange={(e) => form.setData('email', e.target.value)} required /></Field>
                    <Field label="Phone" htmlFor="al-phone"><Input id="al-phone" value={form.data.phone} onChange={(e) => form.setData('phone', e.target.value)} /></Field>
                    <Field label="Company" htmlFor="al-co"><Input id="al-co" value={form.data.company_name} onChange={(e) => form.setData('company_name', e.target.value)} /></Field>
                </div>
                <Field label="What do they need?" htmlFor="al-msg" error={form.errors.message}><Textarea id="al-msg" rows={4} value={form.data.message} onChange={(e) => form.setData('message', e.target.value)} required /></Field>
                <div className="flex justify-end gap-2"><Button type="button" variant="secondary" onClick={onClose}>Cancel</Button><Button disabled={form.processing}>Add lead</Button></div>
            </form>
        </Dialog>
    );
}
