import { Head, Link, router, useForm } from '@inertiajs/react';
import {
    CalendarClock,
    CheckCircle2,
    PhoneCall,
    Plus,
    Save,
    Sparkles,
    Target,
    TrendingUp,
    Users,
} from 'lucide-react';
import { useEffect, useState } from 'react';
import { Field } from '@/components/crm/form-field';
import { KpiTile } from '@/components/crm/kpi-tile';
import { NativeSelect } from '@/components/crm/native-select';
import { PageHeader } from '@/components/crm/page-header';
import { PriorityBadge, StatusLabel } from '@/components/crm/status-badge';
import {
    DataPagination,
    FilterBar,
    FilterField,
    SearchInput,
    SegmentedControl,
    TableCard,
} from '@/components/crm/toolbar';
import { Button } from '@/components/ui/button';
import {
    Dialog,
    DialogContent,
    DialogDescription,
    DialogFooter,
    DialogHeader,
    DialogTitle,
} from '@/components/ui/dialog';
import { Input } from '@/components/ui/input';
import {
    Table,
    TableBody,
    TableCell,
    TableHead,
    TableHeader,
    TableRow,
} from '@/components/ui/table';
import { formatCompactCurrency, formatDate } from '@/lib/format';
import { contact, index as leadsIndex, store } from '@/routes/sales/leads';
import { index as quotationsIndex } from '@/routes/sales/quotations';
import type { Paginated } from '@/types';

type Option = { value: string; label: string };
type StatusOption = Option & { color: string; waiting_on?: string };

type LeadRow = {
    id: number;
    lead_number: string;
    name: string;
    phone: string | null;
    email: string | null;
    address_summary: string | null;
    source: Option | null;
    status: StatusOption;
    priority: { value: string; label: string; color: string };
    assigned_to: { id: number; name: string } | null;
    customer: { id: number; name: string } | null;
    received_on: string | null;
    next_follow_up_on: string | null;
    last_contacted_at: string | null;
    follow_up_overdue: boolean;
    requested_capacity_kw: string | null;
    requested_battery_kwh: string | null;
    budget: string | null;
    notes: string | null;
};

type Filters = {
    search: string | null;
    status: string | null;
    source: string | null;
    assigned: number | null;
    scope: string;
};

export default function Leads({
    leads,
    filters,
    options,
    stats,
    can,
}: {
    leads: Paginated<LeadRow>;
    filters: Filters;
    options: {
        leadStatuses: StatusOption[];
        leadSources: Option[];
        priorities: Option[];
        states: Option[];
        contactMethods: Option[];
        staff: Array<{ value: number; label: string }>;
    };
    stats: {
        open: number;
        due: number;
        new_this_week: number;
        won_this_month: number;
        open_value: number;
    };
    can: { create: boolean; update: boolean; delete: boolean };
}) {
    const [search, setSearch] = useState(filters.search ?? '');
    const [showCreate, setShowCreate] = useState(false);
    const [contacting, setContacting] = useState<LeadRow | null>(null);

    useEffect(() => {
        setSearch(filters.search ?? '');
    }, [filters.search]);

    const apply = (changes: Partial<Filters>) => {
        const query = { ...filters, ...changes, search: search || null };

        router.get(leadsIndex().url, query, {
            preserveState: true,
            preserveScroll: true,
            replace: true,
        });
    };

    return (
        <>
            <Head title="Sales leads" />

            <div className="flex flex-col gap-5">
                <PageHeader
                    eyebrow={
                        <>
                            <TrendingUp className="size-3.5 text-solar" />
                            <span>Sales</span>
                        </>
                    }
                    title="Leads"
                    description="Every enquiry before it becomes an install. The list is sorted by the next follow-up, because a lead nobody called back is worth nothing."
                    actions={
                        <>
                            <Button variant="ghost" size="sm" asChild>
                                <Link href={quotationsIndex()}>Quotations</Link>
                            </Button>
                            {can.create ? (
                                <Button
                                    size="sm"
                                    onClick={() => setShowCreate(true)}
                                >
                                    <Plus className="size-4" />
                                    New lead
                                </Button>
                            ) : null}
                        </>
                    }
                />

                <div className="grid gap-3 sm:grid-cols-2 xl:grid-cols-4">
                    <KpiTile
                        label="Open leads"
                        value={stats.open}
                        hint="Enquiries still being worked"
                        icon={Users}
                        tone="blue"
                        href={leadsIndex({ query: { scope: 'open' } }).url}
                    />
                    <KpiTile
                        label="Follow-ups due"
                        value={stats.due}
                        hint="Today or already overdue"
                        icon={CalendarClock}
                        tone={stats.due > 0 ? 'danger' : 'slate'}
                        href={leadsIndex({ query: { scope: 'due' } }).url}
                    />
                    <KpiTile
                        label="New this week"
                        value={stats.new_this_week}
                        hint="Since Monday"
                        icon={Sparkles}
                        tone="violet"
                    />
                    <KpiTile
                        label="Open pipeline value"
                        value={formatCompactCurrency(stats.open_value)}
                        hint={`${stats.won_this_month} won this month`}
                        icon={Target}
                        tone="success"
                    />
                </div>

                <form
                    onSubmit={(event) => {
                        event.preventDefault();
                        apply({});
                    }}
                >
                    <FilterBar
                        actions={
                            <SegmentedControl
                                value={filters.scope}
                                onChange={(scope) => apply({ scope })}
                                options={[
                                    { value: 'open', label: 'Open' },
                                    {
                                        value: 'due',
                                        label: 'Due',
                                        count: stats.due,
                                    },
                                    { value: 'mine', label: 'Mine' },
                                    { value: 'won', label: 'Won' },
                                    { value: 'lost', label: 'Lost' },
                                    { value: 'all', label: 'All' },
                                ]}
                            />
                        }
                    >
                        <SearchInput
                            value={search}
                            onChange={setSearch}
                            placeholder="Name, phone, suburb or lead number"
                        />
                        <FilterField label="Status">
                            <NativeSelect
                                value={filters.status ?? ''}
                                onChange={(event) =>
                                    apply({
                                        status: event.target.value || null,
                                    })
                                }
                                className="h-9 w-44"
                            >
                                <option value="">Any status</option>
                                {options.leadStatuses.map((status) => (
                                    <option
                                        key={status.value}
                                        value={status.value}
                                    >
                                        {status.label}
                                    </option>
                                ))}
                            </NativeSelect>
                        </FilterField>
                        <FilterField label="Source">
                            <NativeSelect
                                value={filters.source ?? ''}
                                onChange={(event) =>
                                    apply({
                                        source: event.target.value || null,
                                    })
                                }
                                className="h-9 w-40"
                            >
                                <option value="">Any source</option>
                                {options.leadSources.map((source) => (
                                    <option
                                        key={source.value}
                                        value={source.value}
                                    >
                                        {source.label}
                                    </option>
                                ))}
                            </NativeSelect>
                        </FilterField>
                        <FilterField label="Owner">
                            <NativeSelect
                                value={filters.assigned ?? ''}
                                onChange={(event) =>
                                    apply({
                                        assigned: event.target.value
                                            ? Number(event.target.value)
                                            : null,
                                    })
                                }
                                className="h-9 w-40"
                            >
                                <option value="">Anyone</option>
                                {options.staff.map((person) => (
                                    <option
                                        key={person.value}
                                        value={person.value}
                                    >
                                        {person.label}
                                    </option>
                                ))}
                            </NativeSelect>
                        </FilterField>
                    </FilterBar>
                </form>

                <TableCard>
                    <div className="crm-scroll overflow-x-auto">
                        <Table>
                            <TableHeader>
                                <TableRow className="hover:bg-transparent">
                                    <TableHead>Lead</TableHead>
                                    <TableHead>Status</TableHead>
                                    <TableHead>Source</TableHead>
                                    <TableHead>Owner</TableHead>
                                    <TableHead>Next follow-up</TableHead>
                                    <TableHead className="text-right">
                                        Value
                                    </TableHead>
                                    {can.update ? <TableHead /> : null}
                                </TableRow>
                            </TableHeader>
                            <TableBody>
                                {leads.data.length === 0 ? (
                                    <TableRow>
                                        <TableCell
                                            colSpan={can.update ? 7 : 6}
                                            className="px-4 py-10 text-center text-sm text-muted-foreground"
                                        >
                                            No leads match these filters.
                                        </TableCell>
                                    </TableRow>
                                ) : null}
                                {leads.data.map((lead) => (
                                    <TableRow key={lead.id}>
                                        <TableCell>
                                            <span className="block text-sm font-medium">
                                                {lead.name}
                                            </span>
                                            <span className="block font-mono text-xs text-muted-foreground">
                                                {lead.lead_number}
                                            </span>
                                            <span className="block text-xs text-muted-foreground">
                                                {[
                                                    lead.phone,
                                                    lead.address_summary,
                                                ]
                                                    .filter(Boolean)
                                                    .join(' · ') || '—'}
                                            </span>
                                        </TableCell>
                                        <TableCell>
                                            <StatusLabel
                                                tone={lead.status.color}
                                            >
                                                {lead.status.label}
                                            </StatusLabel>
                                            <span className="mt-0.5 block text-[11px] text-muted-foreground">
                                                {lead.status.waiting_on}
                                            </span>
                                        </TableCell>
                                        <TableCell className="text-xs text-muted-foreground">
                                            {lead.source?.label ?? '—'}
                                        </TableCell>
                                        <TableCell className="text-xs">
                                            {lead.assigned_to?.name ??
                                                'Unassigned'}
                                        </TableCell>
                                        <TableCell className="text-xs">
                                            <span
                                                className={
                                                    lead.follow_up_overdue
                                                        ? 'font-medium text-destructive'
                                                        : ''
                                                }
                                            >
                                                {lead.next_follow_up_on
                                                    ? formatDate(
                                                          lead.next_follow_up_on,
                                                      )
                                                    : 'Not set'}
                                            </span>
                                            {lead.last_contacted_at ? (
                                                <span className="block text-[11px] text-muted-foreground">
                                                    Last contact{' '}
                                                    {formatDate(
                                                        lead.last_contacted_at,
                                                    )}
                                                </span>
                                            ) : null}
                                        </TableCell>
                                        <TableCell className="text-right text-sm crm-num">
                                            {lead.budget
                                                ? formatCompactCurrency(
                                                      Number(lead.budget),
                                                  )
                                                : '—'}
                                            <PriorityBadge
                                                priority={lead.priority}
                                            />
                                        </TableCell>
                                        {can.update ? (
                                            <TableCell className="text-right">
                                                <Button
                                                    variant="ghost"
                                                    size="sm"
                                                    onClick={() =>
                                                        setContacting(lead)
                                                    }
                                                >
                                                    <PhoneCall className="size-4" />
                                                    Log contact
                                                </Button>
                                            </TableCell>
                                        ) : null}
                                    </TableRow>
                                ))}
                            </TableBody>
                        </Table>
                    </div>
                    <DataPagination page={leads} noun="leads" />
                </TableCard>
            </div>

            {can.create ? (
                <LeadDialog
                    open={showCreate}
                    options={options}
                    onClose={() => setShowCreate(false)}
                />
            ) : null}

            {contacting ? (
                <ContactDialog
                    lead={contacting}
                    statuses={options.leadStatuses}
                    onClose={() => setContacting(null)}
                />
            ) : null}
        </>
    );
}

function LeadDialog({
    open,
    options,
    onClose,
}: {
    open: boolean;
    options: {
        leadStatuses: StatusOption[];
        leadSources: Option[];
        priorities: Option[];
        states: Option[];
        contactMethods: Option[];
        staff: Array<{ value: number; label: string }>;
    };
    onClose: () => void;
}) {
    const form = useForm({
        name: '',
        phone: '',
        email: '',
        address_line1: '',
        suburb: '',
        state: '',
        postcode: '',
        lead_source: '',
        status: 'new',
        priority: 'normal',
        assigned_to: '',
        property_type: '',
        requirements: '',
        requested_capacity_kw: '',
        requested_battery_kwh: '',
        budget: '',
        preferred_contact_method: '',
        next_follow_up_on: '',
        notes: '',
    });

    const submit = () => {
        form.post(store().url, {
            preserveScroll: true,
            onSuccess: () => {
                form.reset();
                onClose();
            },
        });
    };

    return (
        <Dialog open={open} onOpenChange={(state) => !state && onClose()}>
            <DialogContent className="sm:max-w-2xl">
                <DialogHeader>
                    <DialogTitle>New lead</DialogTitle>
                    <DialogDescription>
                        Only the name is required. The phone number and address
                        make it useful, and the follow-up date makes it get
                        called.
                    </DialogDescription>
                </DialogHeader>

                <form
                    onSubmit={(event) => {
                        event.preventDefault();
                        submit();
                    }}
                    className="grid gap-3 sm:grid-cols-2"
                >
                    <Field label="Name" error={form.errors.name} required>
                        <Input
                            value={form.data.name}
                            onChange={(event) =>
                                form.setData('name', event.target.value)
                            }
                            required
                        />
                    </Field>
                    <Field label="Phone" error={form.errors.phone}>
                        <Input
                            value={form.data.phone}
                            onChange={(event) =>
                                form.setData('phone', event.target.value)
                            }
                        />
                    </Field>
                    <Field label="Email" error={form.errors.email}>
                        <Input
                            type="email"
                            value={form.data.email}
                            onChange={(event) =>
                                form.setData('email', event.target.value)
                            }
                        />
                    </Field>
                    <Field label="Source" error={form.errors.lead_source}>
                        <NativeSelect
                            value={form.data.lead_source}
                            onChange={(event) =>
                                form.setData('lead_source', event.target.value)
                            }
                        >
                            <option value="">Not recorded</option>
                            {options.leadSources.map((source) => (
                                <option key={source.value} value={source.value}>
                                    {source.label}
                                </option>
                            ))}
                        </NativeSelect>
                    </Field>
                    <Field
                        label="Address"
                        error={form.errors.address_line1}
                        className="sm:col-span-2"
                    >
                        <Input
                            value={form.data.address_line1}
                            onChange={(event) =>
                                form.setData(
                                    'address_line1',
                                    event.target.value,
                                )
                            }
                        />
                    </Field>
                    <Field label="Suburb" error={form.errors.suburb}>
                        <Input
                            value={form.data.suburb}
                            onChange={(event) =>
                                form.setData('suburb', event.target.value)
                            }
                        />
                    </Field>
                    <div className="grid grid-cols-2 gap-3">
                        <Field label="State" error={form.errors.state}>
                            <NativeSelect
                                value={form.data.state}
                                onChange={(event) =>
                                    form.setData('state', event.target.value)
                                }
                            >
                                <option value="">—</option>
                                {options.states.map((state) => (
                                    <option
                                        key={state.value}
                                        value={state.value}
                                    >
                                        {state.label}
                                    </option>
                                ))}
                            </NativeSelect>
                        </Field>
                        <Field label="Postcode" error={form.errors.postcode}>
                            <Input
                                value={form.data.postcode}
                                onChange={(event) =>
                                    form.setData('postcode', event.target.value)
                                }
                            />
                        </Field>
                    </div>
                    <Field label="Assigned to" error={form.errors.assigned_to}>
                        <NativeSelect
                            value={form.data.assigned_to}
                            onChange={(event) =>
                                form.setData('assigned_to', event.target.value)
                            }
                        >
                            <option value="">Me</option>
                            {options.staff.map((person) => (
                                <option key={person.value} value={person.value}>
                                    {person.label}
                                </option>
                            ))}
                        </NativeSelect>
                    </Field>
                    <Field label="Priority" error={form.errors.priority}>
                        <NativeSelect
                            value={form.data.priority}
                            onChange={(event) =>
                                form.setData('priority', event.target.value)
                            }
                        >
                            {options.priorities.map((priority) => (
                                <option
                                    key={priority.value}
                                    value={priority.value}
                                >
                                    {priority.label}
                                </option>
                            ))}
                        </NativeSelect>
                    </Field>
                    <Field
                        label="Next follow-up"
                        error={form.errors.next_follow_up_on}
                    >
                        <Input
                            type="date"
                            value={form.data.next_follow_up_on}
                            onChange={(event) =>
                                form.setData(
                                    'next_follow_up_on',
                                    event.target.value,
                                )
                            }
                        />
                    </Field>
                    <Field label="Budget" error={form.errors.budget}>
                        <Input
                            type="number"
                            min={0}
                            step="0.01"
                            value={form.data.budget}
                            onChange={(event) =>
                                form.setData('budget', event.target.value)
                            }
                        />
                    </Field>
                    <Field
                        label="Requested kW"
                        error={form.errors.requested_capacity_kw}
                    >
                        <Input
                            type="number"
                            min={0}
                            step="0.01"
                            value={form.data.requested_capacity_kw}
                            onChange={(event) =>
                                form.setData(
                                    'requested_capacity_kw',
                                    event.target.value,
                                )
                            }
                        />
                    </Field>
                    <Field
                        label="Requested battery kWh"
                        error={form.errors.requested_battery_kwh}
                    >
                        <Input
                            type="number"
                            min={0}
                            step="0.01"
                            value={form.data.requested_battery_kwh}
                            onChange={(event) =>
                                form.setData(
                                    'requested_battery_kwh',
                                    event.target.value,
                                )
                            }
                        />
                    </Field>
                    <Field
                        label="Requirements"
                        error={form.errors.requirements}
                        className="sm:col-span-2"
                    >
                        <textarea
                            value={form.data.requirements}
                            onChange={(event) =>
                                form.setData('requirements', event.target.value)
                            }
                            rows={3}
                            className="w-full rounded-md border border-input bg-transparent px-3 py-2 text-sm outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50"
                        />
                    </Field>

                    <DialogFooter className="sm:col-span-2">
                        <Button type="button" variant="ghost" onClick={onClose}>
                            Cancel
                        </Button>
                        <Button type="submit" disabled={form.processing}>
                            <Save className="size-4" />
                            Create lead
                        </Button>
                    </DialogFooter>
                </form>
            </DialogContent>
        </Dialog>
    );
}

function ContactDialog({
    lead,
    statuses,
    onClose,
}: {
    lead: LeadRow;
    statuses: StatusOption[];
    onClose: () => void;
}) {
    const form = useForm({
        status: lead.status.value,
        next_follow_up_on: '',
        notes: '',
    });

    const submit = () => {
        form.post(contact(lead.id).url, {
            preserveScroll: true,
            onSuccess: onClose,
        });
    };

    return (
        <Dialog open onOpenChange={(state) => !state && onClose()}>
            <DialogContent className="sm:max-w-md">
                <DialogHeader>
                    <DialogTitle>Log contact with {lead.name}</DialogTitle>
                    <DialogDescription>
                        Recording the call moves the lead on and sets the next
                        date in one go.
                    </DialogDescription>
                </DialogHeader>

                <form
                    onSubmit={(event) => {
                        event.preventDefault();
                        submit();
                    }}
                    className="grid gap-3"
                >
                    <Field label="Outcome / status">
                        <NativeSelect
                            value={form.data.status}
                            onChange={(event) =>
                                form.setData('status', event.target.value)
                            }
                        >
                            {statuses.map((status) => (
                                <option key={status.value} value={status.value}>
                                    {status.label}
                                </option>
                            ))}
                        </NativeSelect>
                    </Field>
                    <Field
                        label="Next follow-up"
                        error={form.errors.next_follow_up_on}
                    >
                        <Input
                            type="date"
                            value={form.data.next_follow_up_on}
                            onChange={(event) =>
                                form.setData(
                                    'next_follow_up_on',
                                    event.target.value,
                                )
                            }
                        />
                    </Field>
                    <Field label="Note" error={form.errors.notes}>
                        <textarea
                            value={form.data.notes}
                            onChange={(event) =>
                                form.setData('notes', event.target.value)
                            }
                            rows={3}
                            className="w-full rounded-md border border-input bg-transparent px-3 py-2 text-sm outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50"
                        />
                    </Field>

                    <DialogFooter>
                        <Button type="button" variant="ghost" onClick={onClose}>
                            Cancel
                        </Button>
                        <Button type="submit" disabled={form.processing}>
                            <CheckCircle2 className="size-4" />
                            Save contact
                        </Button>
                    </DialogFooter>
                </form>
            </DialogContent>
        </Dialog>
    );
}
