import { Head, Link, router } from "@inertiajs/react";
import {
    History,
    KeyRound,
    LogIn,
    ShieldAlert,
    TriangleAlert,
    UserRoundCheck,
    Users,
} from "lucide-react";
import { useState, type FormEvent } from "react";
import { StatStrip } from "@/components/crm/kpi-tile";
import { NativeSelect } from "@/components/crm/native-select";
import {
    Callout,
    EmptyState,
    PageHeader,
} from "@/components/crm/page-header";
import { StatusPill } from "@/components/crm/status-badge";
import {
    DataPagination,
    FilterBar,
    FilterField,
    SearchInput,
    TableCard,
} from "@/components/crm/toolbar";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import {
    Table,
    TableBody,
    TableCell,
    TableHead,
    TableHeader,
    TableRow,
} from "@/components/ui/table";
import { formatDate, formatRelative } from "@/lib/format";
import { cn } from "@/lib/utils";
import type {
    Paginated,
    SignInAlert,
    SignInEntry,
    SignInSource,
    SignInStats,
    Option,
} from "@/types";

type Props = {
    events: Paginated<SignInEntry>;
    filters: {
        search: string | null;
        event: string | null;
        source: string | null;
        from: string | null;
        to: string | null;
    };
    sources: SignInSource[];
    eventTypes: Array<Option & { tone: string }>;
    stats: SignInStats;
    alerts: SignInAlert[];
};

const headClass =
    "[&_th]:text-[11px] [&_th]:font-semibold [&_th]:tracking-wide [&_th]:uppercase";

const timeFormatter = new Intl.DateTimeFormat("en-AU", {
    hour: "numeric",
    minute: "2-digit",
});

function timeOf(value: string | null): string {
    if (!value) {
        return "—";
    }

    const date = new Date(value);

    return Number.isNaN(date.getTime()) ? "—" : timeFormatter.format(date);
}

/**
 * The sign-in history: every attempt at every door.
 *
 * The failures lead the page. A list of successful sign-ins is reassuring and
 * dull; what the owner needs to see first is an address that has tried four
 * times in the last hour, and which door somebody was pushing on.
 */
export default function SignIns({
    events,
    filters,
    sources,
    eventTypes,
    stats,
    alerts,
}: Props) {
    const [search, setSearch] = useState(filters.search ?? "");
    const [event, setEvent] = useState(filters.event ?? "");
    const [source, setSource] = useState(filters.source ?? "");
    const [from, setFrom] = useState(filters.from ?? "");
    const [to, setTo] = useState(filters.to ?? "");

    const sourceNotes = Object.fromEntries(
        sources.map((item) => [item.value, item.description]),
    );

    const apply = (next?: {
        search?: string;
        event?: string;
        source?: string;
        from?: string;
        to?: string;
    }): void => {
        const params: Record<string, string> = {};

        const values = {
            search: next?.search ?? search,
            event: next?.event ?? event,
            source: next?.source ?? source,
            from: next?.from ?? from,
            to: next?.to ?? to,
        };

        for (const [key, value] of Object.entries(values)) {
            if (value.trim()) {
                params[key] = value.trim();
            }
        }

        router.get("/settings/audit/sign-ins", params, {
            preserveState: true,
            preserveScroll: true,
            replace: true,
        });
    };

    const submit = (formEvent: FormEvent): void => {
        formEvent.preventDefault();
        apply();
    };

    const reset = (): void => {
        setSearch("");
        setEvent("");
        setSource("");
        setFrom("");
        setTo("");
        router.get(
            "/settings/audit/sign-ins",
            {},
            { preserveScroll: true, replace: true },
        );
    };

    const filtered = Boolean(search || event || source || from || to);

    return (
        <>
            <Head title="Sign-in history" />

            <PageHeader
                eyebrow={
                    <>
                        <KeyRound className="size-3.5" />
                        <span>Owner only</span>
                        <span aria-hidden className="text-muted-foreground/50">
                            ·
                        </span>
                        <span>Passwords are never recorded</span>
                    </>
                }
                title="Sign-in history"
                description="Every attempt at the CRM, the customer portal and the shared status board — successful, failed and signed out — with the address and device each one came from."
                actions={
                    <>
                        <Button variant="outline" size="sm" asChild>
                            <Link href="/settings/audit">
                                <History className="size-4" />
                                Activity log
                            </Link>
                        </Button>
                        <Button variant="outline" size="sm" asChild>
                            <Link href="/settings/audit/deleted">
                                <ShieldAlert className="size-4" />
                                Recycle bin
                            </Link>
                        </Button>
                    </>
                }
            />

            <StatStrip
                items={[
                    {
                        label: "Signed in today",
                        value: stats.signed_in_today,
                        tone: "success",
                        icon: LogIn,
                    },
                    {
                        label: "Failed today",
                        value: stats.failed_today,
                        tone: "danger",
                        icon: TriangleAlert,
                    },
                    {
                        label: "People this week",
                        value: stats.people_this_week,
                        tone: "blue",
                        icon: Users,
                    },
                    {
                        label: "Failures this week",
                        value: stats.failed_this_week,
                        tone: "warning",
                        icon: ShieldAlert,
                    },
                ]}
            />

            {alerts.length > 0 ? (
                <Callout
                    tone="danger"
                    icon={ShieldAlert}
                    title="Repeated failures in the last 24 hours"
                >
                    <ul className="mt-1 grid gap-1">
                        {alerts.map((alert) => (
                            <li
                                key={alert.email}
                                className="flex flex-wrap items-baseline gap-2"
                            >
                                <span className="font-medium">
                                    {alert.email}
                                </span>
                                <span className="crm-num text-xs">
                                    {alert.attempts} attempts
                                </span>
                                <span className="text-xs opacity-70">
                                    last {formatRelative(alert.last_attempt)}
                                </span>
                            </li>
                        ))}
                    </ul>
                </Callout>
            ) : null}

            <form onSubmit={submit}>
                <FilterBar
                    actions={
                        <>
                            <Button type="submit" size="sm">
                                Apply
                            </Button>
                            <Button
                                type="button"
                                size="sm"
                                variant="ghost"
                                onClick={reset}
                            >
                                Reset
                            </Button>
                        </>
                    }
                >
                    <FilterField label="Search" className="min-w-[14rem] flex-1">
                        <SearchInput
                            value={search}
                            onChange={setSearch}
                            placeholder="Name, email or IP address"
                        />
                    </FilterField>

                    <FilterField label="Result" className="w-36">
                        <NativeSelect
                            value={event}
                            onChange={(input) => setEvent(input.target.value)}
                        >
                            <option value="">Any</option>
                            {eventTypes.map((type) => (
                                <option key={type.value} value={type.value}>
                                    {type.label}
                                </option>
                            ))}
                        </NativeSelect>
                    </FilterField>

                    <FilterField label="Door" className="w-40">
                        <NativeSelect
                            value={source}
                            onChange={(input) => setSource(input.target.value)}
                        >
                            <option value="">Every door</option>
                            {sources.map((item) => (
                                <option key={item.value} value={item.value}>
                                    {item.label}
                                </option>
                            ))}
                        </NativeSelect>
                    </FilterField>

                    <FilterField label="From" className="w-36">
                        <Input
                            type="date"
                            value={from}
                            onChange={(input) => setFrom(input.target.value)}
                            className="h-9"
                        />
                    </FilterField>

                    <FilterField label="To" className="w-36">
                        <Input
                            type="date"
                            value={to}
                            onChange={(input) => setTo(input.target.value)}
                            className="h-9"
                        />
                    </FilterField>
                </FilterBar>
            </form>

            <TableCard>
                {events.data.length === 0 ? (
                    <EmptyState
                        icon={KeyRound}
                        title={
                            filtered
                                ? "No attempt matches those filters"
                                : "Nobody has tried to sign in yet"
                        }
                        description={
                            filtered
                                ? "Try a different result, door or date range."
                                : "The first sign-in — and the first failed one — will be recorded here."
                        }
                    />
                ) : (
                    <Table>
                        <TableHeader>
                            <TableRow>
                                <TableHead className={headClass}>When</TableHead>
                                <TableHead className={headClass}>
                                    Person
                                </TableHead>
                                <TableHead className={headClass}>
                                    Result
                                </TableHead>
                                <TableHead className={headClass}>Door</TableHead>
                                <TableHead className={headClass}>
                                    From
                                </TableHead>
                                <TableHead className={headClass}>Device</TableHead>
                                <TableHead className={headClass}>Note</TableHead>
                            </TableRow>
                        </TableHeader>
                        <TableBody>
                            {events.data.map((entry) => (
                                <TableRow key={entry.id}>
                                    <TableCell className="whitespace-nowrap">
                                        <div className="flex flex-col">
                                            <span className="text-sm">
                                                {timeOf(entry.at)}
                                            </span>
                                            <span className="text-[11px] text-muted-foreground">
                                                {formatDate(entry.at)}
                                            </span>
                                        </div>
                                    </TableCell>
                                    <TableCell>
                                        <div className="flex min-w-0 flex-col">
                                            <span className="truncate text-sm font-medium">
                                                {entry.name}
                                            </span>
                                            {entry.email &&
                                            entry.email !== entry.name ? (
                                                <span className="truncate text-[11px] text-muted-foreground">
                                                    {entry.email}
                                                </span>
                                            ) : null}
                                        </div>
                                    </TableCell>
                                    <TableCell>
                                        <StatusPill tone={entry.event.tone}>
                                            {entry.event.label}
                                        </StatusPill>
                                    </TableCell>
                                    <TableCell>
                                        <span
                                            title={sourceNotes[entry.source.value]}
                                        >
                                            <StatusPill tone={entry.source.tone}>
                                                {entry.source.short}
                                            </StatusPill>
                                        </span>
                                    </TableCell>
                                    <TableCell className="crm-num text-xs whitespace-nowrap">
                                        {entry.ip ?? "—"}
                                    </TableCell>
                                    <TableCell className="text-xs text-muted-foreground whitespace-nowrap">
                                        {entry.device}
                                    </TableCell>
                                    <TableCell
                                        className={cn(
                                            "max-w-[16rem] text-xs",
                                            entry.reason
                                                ? "text-foreground"
                                                : "text-muted-foreground",
                                        )}
                                    >
                                        {entry.reason ?? "—"}
                                    </TableCell>
                                </TableRow>
                            ))}
                        </TableBody>
                    </Table>
                )}

                <DataPagination page={events} noun="attempts" />
            </TableCard>

            <div className="grid gap-2 text-[11px] text-muted-foreground">
                {sources.map((item) => (
                    <p key={item.value} className="flex items-start gap-2">
                        <UserRoundCheck className="mt-0.5 size-3.5 shrink-0 opacity-60" />
                        <span>
                            <span className="text-foreground font-medium">
                                {item.label}
                            </span>{" "}
                            — {item.description}
                        </span>
                    </p>
                ))}
            </div>
        </>
    );
}
