import { Head, router, useForm } from '@inertiajs/react';
import {
    CalendarClock,
    CheckCircle2,
    FileCheck2,
    FileWarning,
    Plus,
    Save,
    Send,
} 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 { 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 { formatDate } from '@/lib/format';
import {
    index as lodgementsIndex,
    store,
    update,
} from '@/routes/finance/lodgements';
import type { Paginated } from '@/types';

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

type LodgementRow = {
    id: number;
    reference: string;
    job: { id: number; job_number: string } | null;
    customer: { id: number; name: string; customer_number: string } | null;
    authority: string | null;
    state: string | null;
    state_label: string | null;
    application_reference: string | null;
    status: StatusOption;
    submitted_on: string | null;
    follow_up_on: string | null;
    decided_on: string | null;
    follow_up_overdue: boolean;
    required_documents: string | null;
    missing_documents: string | null;
    outcome_notes: string | null;
    notes: string | null;
};

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

export default function Lodgements({
    lodgements,
    filters,
    options,
    stats,
    can,
}: {
    lodgements: Paginated<LodgementRow>;
    filters: Filters;
    options: {
        lodgementStatuses: StatusOption[];
        states: Option[];
        jobs: Array<{ value: number; label: string }>;
        customers: Array<{ value: number; label: string }>;
    };
    stats: {
        needing_action: number;
        overdue_follow_ups: number;
        awaiting_documents: number;
        submitted_this_month: number;
        approved_this_month: number;
    };
    can: { manage: boolean };
}) {
    const [search, setSearch] = useState(filters.search ?? '');
    const [showCreate, setShowCreate] = useState(false);
    const [editing, setEditing] = useState<LodgementRow | null>(null);

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

    const apply = (changes: Partial<Filters>) => {
        router.get(
            lodgementsIndex().url,
            { ...filters, ...changes, search: search || null },
            { preserveState: true, preserveScroll: true, replace: true },
        );
    };

    return (
        <>
            <Head title="Export lodgements" />

            <div className="flex flex-col gap-5">
                <PageHeader
                    eyebrow={
                        <>
                            <FileCheck2 className="size-3.5 text-solar" />
                            <span>Finance</span>
                        </>
                    }
                    title="Export lodgements"
                    description="The paperwork each distributor needs before an install is approved and the rebate is paid. Missing documents are the usual reason a lodgement stalls, so they are recorded on the record itself."
                    actions={
                        can.manage ? (
                            <Button
                                size="sm"
                                onClick={() => setShowCreate(true)}
                            >
                                <Plus className="size-4" />
                                New lodgement
                            </Button>
                        ) : undefined
                    }
                />

                <div className="grid gap-3 sm:grid-cols-2 xl:grid-cols-4">
                    <KpiTile
                        label="Needing action"
                        value={stats.needing_action}
                        hint="Not yet submitted or blocked"
                        icon={FileWarning}
                        tone={stats.needing_action > 0 ? 'warning' : 'slate'}
                        href={
                            lodgementsIndex({ query: { scope: 'action' } }).url
                        }
                    />
                    <KpiTile
                        label="Overdue follow-ups"
                        value={stats.overdue_follow_ups}
                        hint="Chase dates already passed"
                        icon={CalendarClock}
                        tone={stats.overdue_follow_ups > 0 ? 'danger' : 'slate'}
                    />
                    <KpiTile
                        label="Awaiting documents"
                        value={stats.awaiting_documents}
                        hint="Something is missing from the pack"
                        icon={FileWarning}
                        tone="violet"
                    />
                    <KpiTile
                        label="Approved this month"
                        value={stats.approved_this_month}
                        hint={`${stats.submitted_this_month} submitted`}
                        icon={CheckCircle2}
                        tone="success"
                    />
                </div>

                <form
                    onSubmit={(event) => {
                        event.preventDefault();
                        apply({});
                    }}
                >
                    <FilterBar
                        actions={
                            <SegmentedControl
                                value={filters.scope}
                                onChange={(scope) => apply({ scope })}
                                options={[
                                    { value: 'action', label: 'To action' },
                                    { value: 'submitted', label: 'Submitted' },
                                    { value: 'settled', label: 'Settled' },
                                    { value: 'all', label: 'All' },
                                ]}
                            />
                        }
                    >
                        <SearchInput
                            value={search}
                            onChange={setSearch}
                            placeholder="Reference, job, authority or customer"
                        />
                        <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.lodgementStatuses.map((status) => (
                                    <option
                                        key={status.value}
                                        value={status.value}
                                    >
                                        {status.label}
                                    </option>
                                ))}
                            </NativeSelect>
                        </FilterField>
                    </FilterBar>
                </form>

                <TableCard>
                    <div className="crm-scroll overflow-x-auto">
                        <Table>
                            <TableHeader>
                                <TableRow className="hover:bg-transparent">
                                    <TableHead>Lodgement</TableHead>
                                    <TableHead>Install</TableHead>
                                    <TableHead>Authority</TableHead>
                                    <TableHead>Status</TableHead>
                                    <TableHead>Follow-up</TableHead>
                                    {can.manage ? <TableHead /> : null}
                                </TableRow>
                            </TableHeader>
                            <TableBody>
                                {lodgements.data.length === 0 ? (
                                    <TableRow>
                                        <TableCell
                                            colSpan={can.manage ? 6 : 5}
                                            className="px-4 py-10 text-center text-sm text-muted-foreground"
                                        >
                                            No lodgements match these filters.
                                        </TableCell>
                                    </TableRow>
                                ) : null}
                                {lodgements.data.map((lodgement) => (
                                    <TableRow key={lodgement.id}>
                                        <TableCell>
                                            <span className="block font-mono text-xs">
                                                {lodgement.reference}
                                            </span>
                                            <span className="block text-[11px] text-muted-foreground">
                                                {lodgement.application_reference ??
                                                    'No application number'}
                                            </span>
                                        </TableCell>
                                        <TableCell className="text-sm">
                                            {lodgement.job?.job_number ?? '—'}
                                            <span className="block text-[11px] text-muted-foreground">
                                                {lodgement.customer?.name ?? ''}
                                            </span>
                                        </TableCell>
                                        <TableCell className="text-xs">
                                            {lodgement.authority ?? '—'}
                                            <span className="block text-[11px] text-muted-foreground">
                                                {lodgement.state_label ?? ''}
                                            </span>
                                        </TableCell>
                                        <TableCell>
                                            <StatusLabel
                                                tone={lodgement.status.color}
                                            >
                                                {lodgement.status.label}
                                            </StatusLabel>
                                            {lodgement.missing_documents ? (
                                                <span className="mt-0.5 line-clamp-1 block text-[11px] text-destructive">
                                                    Missing:{' '}
                                                    {
                                                        lodgement.missing_documents
                                                    }
                                                </span>
                                            ) : null}
                                        </TableCell>
                                        <TableCell className="text-xs">
                                            <span
                                                className={
                                                    lodgement.follow_up_overdue
                                                        ? 'block font-medium text-destructive'
                                                        : 'block'
                                                }
                                            >
                                                {lodgement.follow_up_on
                                                    ? formatDate(
                                                          lodgement.follow_up_on,
                                                      )
                                                    : 'Not set'}
                                            </span>
                                            <span className="block text-[11px] text-muted-foreground">
                                                Sent{' '}
                                                {formatDate(
                                                    lodgement.submitted_on,
                                                )}
                                            </span>
                                        </TableCell>
                                        {can.manage ? (
                                            <TableCell className="text-right">
                                                <Button
                                                    size="sm"
                                                    variant="ghost"
                                                    onClick={() =>
                                                        setEditing(lodgement)
                                                    }
                                                >
                                                    Update
                                                </Button>
                                            </TableCell>
                                        ) : null}
                                    </TableRow>
                                ))}
                            </TableBody>
                        </Table>
                    </div>
                    <DataPagination page={lodgements} noun="lodgements" />
                </TableCard>
            </div>

            {can.manage ? (
                <>
                    <LodgementDialog
                        key="new"
                        open={showCreate}
                        options={options}
                        onClose={() => setShowCreate(false)}
                    />
                    {editing ? (
                        <LodgementDialog
                            key={editing.id}
                            open
                            lodgement={editing}
                            options={options}
                            onClose={() => setEditing(null)}
                        />
                    ) : null}
                </>
            ) : null}
        </>
    );
}

function LodgementDialog({
    open,
    lodgement,
    options,
    onClose,
}: {
    open: boolean;
    lodgement?: LodgementRow;
    options: {
        lodgementStatuses: StatusOption[];
        states: Option[];
        jobs: Array<{ value: number; label: string }>;
        customers: Array<{ value: number; label: string }>;
    };
    onClose: () => void;
}) {
    const form = useForm({
        job_id: lodgement?.job?.id ? String(lodgement.job.id) : '',
        customer_id: lodgement?.customer?.id
            ? String(lodgement.customer.id)
            : '',
        authority: lodgement?.authority ?? '',
        state: lodgement?.state ?? '',
        application_reference: lodgement?.application_reference ?? '',
        status: lodgement?.status.value ?? 'not_started',
        submitted_on: lodgement?.submitted_on ?? '',
        follow_up_on: lodgement?.follow_up_on ?? '',
        decided_on: lodgement?.decided_on ?? '',
        required_documents: lodgement?.required_documents ?? '',
        missing_documents: lodgement?.missing_documents ?? '',
        outcome_notes: lodgement?.outcome_notes ?? '',
        notes: lodgement?.notes ?? '',
    });

    const submit = () => {
        if (lodgement) {
            form.patch(update(lodgement.id).url, {
                preserveScroll: true,
                onSuccess: onClose,
            });

            return;
        }

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

    return (
        <Dialog open={open} onOpenChange={(state) => !state && onClose()}>
            <DialogContent className="max-h-[90vh] overflow-y-auto sm:max-w-2xl">
                <DialogHeader>
                    <DialogTitle>
                        {lodgement
                            ? `Update ${lodgement.reference}`
                            : 'New lodgement'}
                    </DialogTitle>
                    <DialogDescription>
                        One lodgement per install. Record the dates as they
                        happen; they are what the follow-up list is built from.
                    </DialogDescription>
                </DialogHeader>

                <form
                    onSubmit={(event) => {
                        event.preventDefault();
                        submit();
                    }}
                    className="grid gap-3 sm:grid-cols-2"
                >
                    <Field label="Job" error={form.errors.job_id} required>
                        <NativeSelect
                            value={form.data.job_id}
                            onChange={(event) =>
                                form.setData('job_id', event.target.value)
                            }
                        >
                            <option value="">Choose the job</option>
                            {options.jobs.map((job) => (
                                <option key={job.value} value={job.value}>
                                    {job.label}
                                </option>
                            ))}
                        </NativeSelect>
                    </Field>
                    <Field label="Customer" error={form.errors.customer_id}>
                        <NativeSelect
                            value={form.data.customer_id}
                            onChange={(event) =>
                                form.setData('customer_id', event.target.value)
                            }
                        >
                            <option value="">Same as the job's customer</option>
                            {options.customers.map((customer) => (
                                <option
                                    key={customer.value}
                                    value={customer.value}
                                >
                                    {customer.label}
                                </option>
                            ))}
                        </NativeSelect>
                    </Field>
                    <Field label="Authority" error={form.errors.authority}>
                        <Input
                            value={form.data.authority}
                            onChange={(event) =>
                                form.setData('authority', event.target.value)
                            }
                            placeholder="Distributor or network"
                        />
                    </Field>
                    <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="Status" error={form.errors.status} required>
                        <NativeSelect
                            value={form.data.status}
                            onChange={(event) =>
                                form.setData('status', event.target.value)
                            }
                        >
                            {options.lodgementStatuses.map((status) => (
                                <option key={status.value} value={status.value}>
                                    {status.label}
                                </option>
                            ))}
                        </NativeSelect>
                    </Field>
                    <Field
                        label="Application reference"
                        error={form.errors.application_reference}
                    >
                        <Input
                            value={form.data.application_reference}
                            onChange={(event) =>
                                form.setData(
                                    'application_reference',
                                    event.target.value,
                                )
                            }
                        />
                    </Field>
                    <Field label="Submitted" error={form.errors.submitted_on}>
                        <Input
                            type="date"
                            value={form.data.submitted_on}
                            onChange={(event) =>
                                form.setData('submitted_on', event.target.value)
                            }
                        />
                    </Field>
                    <Field label="Follow up" error={form.errors.follow_up_on}>
                        <Input
                            type="date"
                            value={form.data.follow_up_on}
                            onChange={(event) =>
                                form.setData('follow_up_on', event.target.value)
                            }
                        />
                    </Field>
                    <Field label="Decided" error={form.errors.decided_on}>
                        <Input
                            type="date"
                            value={form.data.decided_on}
                            onChange={(event) =>
                                form.setData('decided_on', event.target.value)
                            }
                        />
                    </Field>
                    <Field
                        label="Required documents"
                        error={form.errors.required_documents}
                    >
                        <Input
                            value={form.data.required_documents}
                            onChange={(event) =>
                                form.setData(
                                    'required_documents',
                                    event.target.value,
                                )
                            }
                        />
                    </Field>
                    <Field
                        label="Missing documents"
                        error={form.errors.missing_documents}
                        className="sm:col-span-2"
                    >
                        <Input
                            value={form.data.missing_documents}
                            onChange={(event) =>
                                form.setData(
                                    'missing_documents',
                                    event.target.value,
                                )
                            }
                        />
                    </Field>
                    <Field
                        label="Outcome notes"
                        error={form.errors.outcome_notes}
                        className="sm:col-span-2"
                    >
                        <textarea
                            rows={3}
                            value={form.data.outcome_notes}
                            onChange={(event) =>
                                form.setData(
                                    'outcome_notes',
                                    event.target.value,
                                )
                            }
                            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}>
                            {lodgement ? (
                                <Save className="size-4" />
                            ) : (
                                <Send className="size-4" />
                            )}
                            {lodgement ? 'Save' : 'Create lodgement'}
                        </Button>
                    </DialogFooter>
                </form>
            </DialogContent>
        </Dialog>
    );
}
