import { useEffect, useState } from 'react';
import { Head, Link, router } from '@inertiajs/react';
import {
    Check,
    ClipboardCheck,
    Copy,
    FileSignature,
    Link2,
    Plus,
    RefreshCw,
    ShieldAlert,
    Smartphone,
    TriangleAlert,
    Unlink,
} from 'lucide-react';
import { EmptyState, PageHeader } from '@/components/crm/page-header';
import { StatusPill } from '@/components/crm/status-badge';
import {
    ActiveFilters,
    DataPagination,
    FilterBar,
    FilterField,
    SearchInput,
    TableCard,
} from '@/components/crm/toolbar';
import { NativeSelect } from '@/components/crm/native-select';
import { Button } from '@/components/ui/button';
import {
    Table,
    TableBody,
    TableCell,
    TableHead,
    TableHeader,
    TableRow,
} from '@/components/ui/table';
import { copyToClipboard } from '@/lib/clipboard';
import { formatDate, formatNumber } from '@/lib/format';
import { cn } from '@/lib/utils';
import { create as createInspection, show as showInspection } from '@/routes/inspections';
import type { InspectionIndexProps, InspectionSummary } from '@/types';

type Filters = InspectionIndexProps['filters'];

const STATUS_TONES: Record<string, string> = {
    invited: 'amber',
    submitted: 'blue',
    reviewed: 'emerald',
    expired: 'slate',
};

/**
 * The inspection reports the office has out with crews, and the ones that have
 * come back.
 *
 * Ordered newest first and grouped by what needs attention: a submitted report
 * nobody has read, then the links still running, then the ones that ran out.
 */
export default function InspectionsIndex({
    reports,
    filters,
    filterOptions,
    counts,
    intake,
    can,
}: InspectionIndexProps) {
    const [search, setSearch] = useState(filters.search ?? '');

    const navigate = (next: Partial<Filters>) => {
        const merged: Filters = { ...filters, ...next };
        const params: Record<string, string> = {};

        Object.entries(merged).forEach(([key, value]) => {
            if (value !== null && value !== undefined && value !== '') {
                params[key] = String(value);
            }
        });

        router.get('/inspections', params, { preserveState: true, replace: true });
    };

    const hasFilters =
        Boolean(filters.search) ||
        filters.status !== 'all' ||
        Boolean(filters.purpose) ||
        Boolean(filters.outcome) ||
        Boolean(filters.source) ||
        Boolean(filters.client) ||
        Boolean(filters.installer);

    const label = (options: Array<{ value: string; label: string }>, value: string | null) =>
        options.find((option) => option.value === value)?.label ?? value ?? '';

    const applied = [
        filters.search
            ? {
                  key: 'search',
                  label: 'Search',
                  value: filters.search,
                  onRemove: () => {
                      setSearch('');
                      navigate({ search: null });
                  },
              }
            : null,
        filters.status !== 'all'
            ? {
                  key: 'status',
                  label: 'Status',
                  value: label(filterOptions.statuses, filters.status),
                  onRemove: () => navigate({ status: 'all' }),
              }
            : null,
        filters.purpose
            ? {
                  key: 'purpose',
                  label: 'Purpose',
                  value: label(filterOptions.purposes, filters.purpose),
                  onRemove: () => navigate({ purpose: null }),
              }
            : null,
        filters.outcome
            ? {
                  key: 'outcome',
                  label: 'Outcome',
                  value: label(filterOptions.outcomes, filters.outcome),
                  onRemove: () => navigate({ outcome: null }),
              }
            : null,
        filters.source
            ? {
                  key: 'source',
                  label: 'Opened by',
                  value: label(filterOptions.sources, filters.source),
                  onRemove: () => navigate({ source: null }),
              }
            : null,
        filters.client
            ? {
                  key: 'client',
                  label: 'Client',
                  value:
                      filterOptions.clients.find(
                          (option) => option.value === filters.client,
                      )?.label ?? filters.client,
                  onRemove: () => navigate({ client: null }),
              }
            : null,
        filters.installer
            ? {
                  key: 'installer',
                  label: 'Crew',
                  value:
                      filterOptions.installers.find(
                          (option) => option.value === filters.installer,
                      )?.label ?? `#${filters.installer}`,
                  onRemove: () => navigate({ installer: null }),
              }
            : null,
    ].filter((item): item is NonNullable<typeof item> => item !== null);

    const tiles = [
        {
            label: 'Open with a crew',
            value: counts.open,
            hint: 'Links still inside their month',
            icon: FileSignature,
            tone: 'text-amber-600 dark:text-amber-400',
        },
        {
            label: 'Waiting to be read',
            value: counts.awaiting_review,
            hint: 'Submitted, nobody has reviewed them',
            icon: ClipboardCheck,
            tone: 'text-blue-600 dark:text-blue-400',
        },
        {
            label: 'Reports with defects',
            value: counts.defects,
            hint: 'Work is owed to the customer',
            icon: TriangleAlert,
            tone: 'text-orange-600 dark:text-orange-400',
        },
        {
            label: 'Failed inspections',
            value: counts.failed,
            hint: 'Do not energise until reinspected',
            icon: ShieldAlert,
            tone: 'text-red-600 dark:text-red-400',
        },
    ];

    return (
        <>
            <Head title="Inspections & warranty" />

            <div className="flex flex-col gap-5">
                <PageHeader
                    eyebrow={
                        <>
                            <ClipboardCheck className="text-solar size-3.5" />
                            <span>Warranty and compliance</span>
                        </>
                    }
                    title="Inspections & warranty"
                    description="A standard Australian post-installation checklist — array, inverter, battery, earthing, labels and paperwork — filled in by the crew through a link. No account needed on site."
                    actions={
                        can.create ? (
                            <Button size="sm" asChild>
                                <Link href={createInspection()}>
                                    <Plus />
                                    Request an inspection
                                </Link>
                            </Button>
                        ) : null
                    }
                />

                <IntakeLinkCard
                    intake={intake}
                    unlinked={counts.unlinked}
                    onShowUnlinked={() => navigate({ client: 'unlinked' })}
                />

                <div className="grid gap-3 sm:grid-cols-2 xl:grid-cols-4">
                    {tiles.map((tile) => (
                        <div
                            key={tile.label}
                            className="bg-card shadow-card rounded-xl p-4 ring-1 ring-hairline"
                        >
                            <div className="flex items-center justify-between gap-3">
                                <p className="text-muted-foreground text-xs font-medium">
                                    {tile.label}
                                </p>
                                <tile.icon className={cn('size-4', tile.tone)} />
                            </div>
                            <p className="crm-num mt-2 text-2xl font-semibold tracking-tight">
                                {formatNumber(tile.value)}
                            </p>
                            <p className="text-muted-foreground mt-1 text-[11px] leading-snug">
                                {tile.hint}
                            </p>
                        </div>
                    ))}
                </div>

                <FilterBar
                    actions={
                        <Button
                            size="sm"
                            variant="outline"
                            onClick={() => navigate({ status: 'submitted' })}
                        >
                            Show what needs reading
                        </Button>
                    }
                >
                    <FilterField label="Search" className="sm:col-span-2">
                        <SearchInput
                            value={search}
                            onChange={setSearch}
                            placeholder="Reference, job number, customer or inspector"
                        />
                    </FilterField>
                    <FilterField label="Status">
                        <NativeSelect
                            value={filters.status}
                            onChange={(event) => navigate({ status: event.target.value })}
                        >
                            {filterOptions.statuses.map((option) => (
                                <option key={option.value} value={option.value}>
                                    {option.label}
                                </option>
                            ))}
                        </NativeSelect>
                    </FilterField>
                    <FilterField label="Purpose">
                        <NativeSelect
                            value={filters.purpose ?? ''}
                            onChange={(event) =>
                                navigate({ purpose: event.target.value || null })
                            }
                        >
                            <option value="">Any purpose</option>
                            {filterOptions.purposes.map((option) => (
                                <option key={option.value} value={option.value}>
                                    {option.label}
                                </option>
                            ))}
                        </NativeSelect>
                    </FilterField>
                    <FilterField label="Outcome">
                        <NativeSelect
                            value={filters.outcome ?? ''}
                            onChange={(event) =>
                                navigate({ outcome: event.target.value || null })
                            }
                        >
                            <option value="">Any outcome</option>
                            {filterOptions.outcomes.map((option) => (
                                <option key={option.value} value={option.value}>
                                    {option.label}
                                </option>
                            ))}
                        </NativeSelect>
                    </FilterField>
                    <FilterField label="Opened by">
                        <NativeSelect
                            value={filters.source ?? ''}
                            onChange={(event) =>
                                navigate({ source: event.target.value || null })
                            }
                        >
                            <option value="">Anyone</option>
                            {filterOptions.sources.map((option) => (
                                <option key={option.value} value={option.value}>
                                    {option.label}
                                </option>
                            ))}
                        </NativeSelect>
                    </FilterField>
                    <FilterField label="Client">
                        <NativeSelect
                            value={filters.client ?? ''}
                            onChange={(event) =>
                                navigate({ client: event.target.value || null })
                            }
                        >
                            <option value="">Any client</option>
                            {filterOptions.clients.map((option) => (
                                <option key={option.value} value={option.value}>
                                    {option.label}
                                </option>
                            ))}
                        </NativeSelect>
                    </FilterField>
                    <FilterField label="Crew">
                        <NativeSelect
                            value={filters.installer ?? ''}
                            onChange={(event) =>
                                navigate({
                                    installer: event.target.value
                                        ? Number(event.target.value)
                                        : null,
                                })
                            }
                        >
                            <option value="">Any crew</option>
                            {filterOptions.installers.map((option) => (
                                <option key={option.value} value={option.value}>
                                    {option.label}
                                </option>
                            ))}
                        </NativeSelect>
                    </FilterField>
                </FilterBar>

                {hasFilters ? (
                    <ActiveFilters
                        filters={applied}
                        onClear={() => {
                            setSearch('');
                            router.get('/inspections');
                        }}
                    />
                ) : null}

                <TableCard>
                    {reports.data.length === 0 ? (
                        <EmptyState
                            icon={FileSignature}
                            title="No inspection reports here"
                            description={
                                hasFilters
                                    ? 'Nothing matches those filters. Clear them to see every report.'
                                    : 'Request one against a job and share the link with the crew who did the work.'
                            }
                            action={
                                can.create ? (
                                    <Button size="sm" asChild>
                                        <Link href={createInspection()}>
                                            <Plus />
                                            Request an inspection
                                        </Link>
                                    </Button>
                                ) : null
                            }
                        />
                    ) : (
                        <Table>
                            <TableHeader>
                                <TableRow>
                                    <TableHead>Report</TableHead>
                                    <TableHead>Job and site</TableHead>
                                    <TableHead>Crew</TableHead>
                                    <TableHead>Outcome</TableHead>
                                    <TableHead>Status</TableHead>
                                    <TableHead className="text-right">Defects</TableHead>
                                </TableRow>
                            </TableHeader>
                            <TableBody>
                                {reports.data.map((report: InspectionSummary) => (
                                    <TableRow key={report.id} className="group">
                                        <TableCell>
                                            <Link
                                                href={showInspection(report.id)}
                                                className="block min-w-0"
                                            >
                                                <span className="crm-num block font-medium group-hover:underline">
                                                    {report.reference}
                                                </span>
                                                <span className="text-muted-foreground flex items-center gap-1 text-xs">
                                                    {report.purpose.label}
                                                    {report.source.value ===
                                                    'self_service' ? (
                                                        <span className="inline-flex items-center gap-0.5 rounded-full bg-violet-500/10 px-1.5 py-0.5 text-[10px] font-medium text-violet-700 dark:text-violet-400">
                                                            <Smartphone className="size-2.5" />
                                                            On site
                                                        </span>
                                                    ) : null}
                                                </span>
                                            </Link>
                                        </TableCell>
                                        <TableCell>
                                            <Link
                                                href={showInspection(report.id)}
                                                className="block min-w-0"
                                            >
                                                <span className="block text-sm">
                                                    {report.job
                                                        ? `Job ${report.job.job_number}`
                                                        : 'No job'}
                                                </span>
                                                <span className="text-muted-foreground block text-xs">
                                                    {report.customer?.name ?? '—'}
                                                    {report.site
                                                        ? ` · ${report.site.suburb}`
                                                        : ''}
                                                </span>
                                                {!report.client_linked ? (
                                                    <span className="mt-0.5 inline-flex items-center gap-0.5 text-[10px] font-medium text-amber-700 dark:text-amber-400">
                                                        <Unlink className="size-2.5" />
                                                        No client linked
                                                    </span>
                                                ) : null}
                                            </Link>
                                        </TableCell>
                                        <TableCell>
                                            <span className="block text-sm">
                                                {report.installer?.name ??
                                                    report.inspector_name ??
                                                    'Not assigned'}
                                            </span>
                                            <span className="text-muted-foreground block text-xs">
                                                {report.inspected_on
                                                    ? `Inspected ${formatDate(report.inspected_on)}`
                                                    : report.sent_at
                                                      ? `Sent ${formatDate(report.sent_at)}`
                                                      : 'Not sent yet'}
                                            </span>
                                        </TableCell>
                                        <TableCell>
                                            {report.outcome ? (
                                                <StatusPill
                                                    tone={
                                                        report.outcome.value === 'pass'
                                                            ? 'emerald'
                                                            : report.outcome.value === 'fail'
                                                              ? 'red'
                                                              : 'amber'
                                                    }
                                                >
                                                    {report.outcome.label}
                                                </StatusPill>
                                            ) : (
                                                <span className="text-muted-foreground text-xs">
                                                    —
                                                </span>
                                            )}
                                        </TableCell>
                                        <TableCell>
                                            <StatusPill
                                                tone={
                                                    STATUS_TONES[report.status.value] ??
                                                    'slate'
                                                }
                                            >
                                                {report.status.label}
                                            </StatusPill>
                                            {report.status.value === 'invited' &&
                                            report.expires_at ? (
                                                <span className="text-muted-foreground mt-1 block text-[11px]">
                                                    Until {formatDate(report.expires_at)}
                                                </span>
                                            ) : null}
                                        </TableCell>
                                        <TableCell className="crm-num text-right">
                                            {report.defect_count > 0 ? (
                                                <span className="font-medium text-orange-600 dark:text-orange-400">
                                                    {report.defect_count}
                                                </span>
                                            ) : (
                                                <span className="text-muted-foreground">
                                                    0
                                                </span>
                                            )}
                                        </TableCell>
                                    </TableRow>
                                ))}
                            </TableBody>
                        </Table>
                    )}
                </TableCard>

                <DataPagination page={reports} noun="report" />
            </div>
        </>
    );
}

/**
 * The standing link a crew keeps on a phone.
 *
 * The office's way — pick the job, open a report, send the link — is still the
 * one in the button above. This is the other door: one address for the business,
 * which a crew sent to a fault can open on site rather than waiting for a form
 * to be issued. The address is the credential, so it is only shown to somebody
 * who may also replace it — rotating the link is how a leak is undone.
 */
function IntakeLinkCard({
    intake,
    unlinked,
    onShowUnlinked,
}: {
    intake: InspectionIndexProps['intake'];
    unlinked: number;
    onShowUnlinked: () => void;
}) {
    const [copied, setCopied] = useState(false);

    useEffect(() => {
        if (!copied) {
            return;
        }

        const timer = window.setTimeout(() => setCopied(false), 2200);

        return () => window.clearTimeout(timer);
    }, [copied]);

    if (!intake.can_manage) {
        return null;
    }

    const copy = async () => {
        if (!intake.url) {
            return;
        }

        // True even on a plain-HTTP host: the helper falls back when the modern
        // clipboard API is not there. The button only says "Copied" when the
        // text really reached the clipboard.
        setCopied(await copyToClipboard(intake.url));
    };

    const post = (path: string) => router.post(path, {}, { preserveScroll: true });

    return (
        <section className="bg-card shadow-card overflow-hidden rounded-xl ring-1 ring-hairline">
            <div className="flex flex-wrap items-start gap-3 p-4">
                <span
                    className={cn(
                        'flex size-9 shrink-0 items-center justify-center rounded-lg ring-1',
                        intake.open
                            ? 'bg-violet-500/10 text-violet-700 ring-violet-500/25 dark:text-violet-400'
                            : 'bg-muted text-muted-foreground ring-hairline',
                    )}
                >
                    <Link2 className="size-4" />
                </span>

                <div className="min-w-0 flex-1">
                    <div className="flex flex-wrap items-center gap-2">
                        <h2 className="text-sm font-semibold">
                            On-site warranty and service link
                        </h2>
                        <StatusPill tone={intake.open ? 'emerald' : 'slate'}>
                            {intake.open ? 'Open' : 'Closed'}
                        </StatusPill>
                    </div>

                    <p className="text-muted-foreground mt-1 max-w-2xl text-xs leading-relaxed">
                        A crew can open this at the property and start the
                        report themselves — they confirm the client name and
                        address, then fill in the same checklist as a report we
                        send. Nothing is created until they confirm.
                    </p>

                    {intake.open && intake.url ? (
                        <div className="mt-3 flex flex-col gap-2 sm:flex-row sm:items-center">
                            <code className="bg-muted/60 ring-hairline min-w-0 flex-1 truncate rounded-md px-2.5 py-2 text-[11px] ring-1">
                                {intake.url}
                            </code>

                            <div className="flex flex-wrap gap-2">
                                <Button
                                    size="sm"
                                    variant="outline"
                                    onClick={copy}
                                >
                                    {copied ? <Check /> : <Copy />}
                                    {copied ? 'Copied' : 'Copy'}
                                </Button>
                                <Button
                                    size="sm"
                                    variant="outline"
                                    onClick={() => post('/inspections/link/rotate')}
                                    title="Issue a new address; every copy of the old one stops working"
                                >
                                    <RefreshCw />
                                    New address
                                </Button>
                                <Button
                                    size="sm"
                                    variant="ghost"
                                    onClick={() => post('/inspections/link/close')}
                                >
                                    Close
                                </Button>
                            </div>
                        </div>
                    ) : (
                        <div className="mt-3 flex flex-wrap items-center gap-2">
                            <Button
                                size="sm"
                                onClick={() => post('/inspections/link')}
                            >
                                <Link2 />
                                Open the link
                            </Button>
                            <span className="text-muted-foreground text-[11px]">
                                Closed links forget their address, so a new one
                                is issued when it is opened.
                            </span>
                        </div>
                    )}

                    {unlinked > 0 ? (
                        <button
                            type="button"
                            onClick={onShowUnlinked}
                            className="mt-3 inline-flex items-center gap-1.5 text-[11px] font-medium text-amber-700 hover:underline dark:text-amber-400"
                        >
                            <Unlink className="size-3" />
                            {unlinked === 1
                                ? 'One report a crew started is not linked to a client'
                                : `${unlinked} reports a crew started are not linked to a client`}
                            — show them
                        </button>
                    ) : null}
                </div>
            </div>
        </section>
    );
}
