import { Head, Link, router, useForm } from "@inertiajs/react";
import {
    ArchiveRestore,
    Box,
    ChevronDown,
    History,
    Info,
    Layers,
    LogIn,
    RotateCcw,
    ShieldCheck,
    Trash2,
} from "lucide-react";
import { useState, type FormEvent } from "react";
import { StatStrip } from "@/components/crm/kpi-tile";
import {
    Callout,
    EmptyState,
    PageHeader,
} from "@/components/crm/page-header";
import { StatusPill } from "@/components/crm/status-badge";
import { toneClasses } from "@/components/crm/tone";
import {
    DataPagination,
    FilterBar,
    FilterField,
    SearchInput,
    TableCard,
} from "@/components/crm/toolbar";
import { Button } from "@/components/ui/button";
import {
    Dialog,
    DialogContent,
    DialogDescription,
    DialogFooter,
    DialogHeader,
    DialogTitle,
} from "@/components/ui/dialog";
import { formatDate, formatRelative } from "@/lib/format";
import { cn } from "@/lib/utils";
import type {
    Paginated,
    RecycleCategory,
    RecycleItem,
    RecycleStats,
} from "@/types";

type Props = {
    items: Paginated<RecycleItem>;
    categories: RecycleCategory[];
    current: RecycleCategory | null;
    filters: {
        type: string | null;
        search: string | null;
    };
    stats: RecycleStats;
};

/**
 * The recycle bin.
 *
 * Removing something in this CRM hides it. This is where the hidden rows are —
 * grouped by the module they came from, so a client is found under Clients and
 * a job under Jobs — and the only action is putting one back. There is no
 * "delete permanently" button, because the whole point is that a mis-click
 * costs nothing.
 */
export default function RecycleBin({
    items,
    categories,
    current,
    filters,
    stats,
}: Props) {
    const [search, setSearch] = useState(filters.search ?? "");
    const [expanded, setExpanded] = useState<string | null>(null);
    const [pending, setPending] = useState<RecycleItem | null>(null);

    // The form exists for one reason: its errors, so a refused restore can say
    // why instead of failing silently. No field is actually sent.
    const restore = useForm({ record: "" });

    const go = (params: { type?: string | null; search?: string }): void => {
        const query: Record<string, string> = {};

        if (params.type) {
            query.type = params.type;
        }

        if (params.search?.trim()) {
            query.search = params.search.trim();
        }

        router.get("/settings/audit/deleted", query, {
            preserveState: true,
            preserveScroll: true,
            replace: true,
        });
    };

    const submitSearch = (event: FormEvent): void => {
        event.preventDefault();
        go({ type: filters.type, search });
    };

    const confirmRestore = (): void => {
        if (!pending) {
            return;
        }

        restore.post(
            `/settings/audit/deleted/${pending.key}/${pending.id}/restore`,
            {
                preserveScroll: true,
                onSuccess: () => setPending(null),
            },
        );
    };

    return (
        <>
            <Head title="Recycle bin" />

            <PageHeader
                eyebrow={
                    <>
                        <ShieldCheck className="size-3.5" />
                        <span>Owner only</span>
                        <span aria-hidden className="text-muted-foreground/50">
                            ·
                        </span>
                        <span>Nothing is ever destroyed from here</span>
                    </>
                }
                title="Recycle bin"
                description="Removing a client, site, job, ticket, account or document hides it; it does not delete it. Everything hidden is listed below by the module it came from, and can be put back exactly as it was."
                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/sign-ins">
                                <LogIn className="size-4" />
                                Sign-in history
                            </Link>
                        </Button>
                    </>
                }
            />

            <StatStrip
                items={[
                    {
                        label: "Hidden records",
                        value: stats.total,
                        tone: stats.total > 0 ? "warning" : "slate",
                        icon: Trash2,
                    },
                    {
                        label: "Modules affected",
                        value: stats.modules,
                        tone: "blue",
                        icon: Layers,
                    },
                    {
                        label: "Can be restored now",
                        value: stats.restorable,
                        tone: "success",
                        icon: RotateCcw,
                    },
                    {
                        label: "Waiting on a parent",
                        value: Math.max(0, stats.total - stats.restorable),
                        tone: "amber",
                        icon: Info,
                    },
                ]}
            />

            {stats.total === 0 ? (
                <TableCard>
                    <EmptyState
                        icon={ArchiveRestore}
                        title="Nothing is hidden"
                        description="When somebody removes a client, a job or a ticket, it will wait here instead of disappearing — ready to come back if it was a mistake."
                    />
                </TableCard>
            ) : (
                <>
                    <div className="grid gap-2 sm:grid-cols-2 lg:grid-cols-3">
                        <CategoryCard
                            label="Everything"
                            module="Newest first"
                            count={stats.total}
                            tone="slate"
                            active={current === null}
                            onClick={() => go({ type: null })}
                        />

                        {categories
                            .filter((category) => category.count > 0)
                            .map((category) => (
                                <CategoryCard
                                    key={category.key}
                                    label={category.module}
                                    module={`${category.count} hidden`}
                                    count={category.count}
                                    tone={category.tone}
                                    active={current?.key === category.key}
                                    onClick={() =>
                                        go({ type: category.key })
                                    }
                                />
                            ))}
                    </div>

                    <form onSubmit={submitSearch}>
                        <FilterBar
                            actions={
                                current ? (
                                    <Button
                                        type="button"
                                        size="sm"
                                        variant="ghost"
                                        onClick={() => {
                                            setSearch("");
                                            go({ type: null });
                                        }}
                                    >
                                        Show everything
                                    </Button>
                                ) : null
                            }
                        >
                            <FilterField
                                label={
                                    current
                                        ? `Search hidden ${current.module.toLowerCase()}`
                                        : "Search"
                                }
                                className="min-w-[16rem] flex-1"
                            >
                                <SearchInput
                                    value={search}
                                    onChange={setSearch}
                                    placeholder={
                                        current
                                            ? `A ${current.label.toLowerCase()} by name, number or address`
                                            : "Pick a module above to search inside it"
                                    }
                                />
                            </FilterField>

                            <Button
                                type="submit"
                                size="sm"
                                disabled={!current}
                            >
                                Search
                            </Button>
                        </FilterBar>
                    </form>

                    {!current ? (
                        <Callout tone="info" icon={Info}>
                            These are the most recently hidden records from
                            every module. Choose one above to see everything it
                            holds, search inside it, and restore.
                        </Callout>
                    ) : null}

                    <TableCard>
                        {items.data.length === 0 ? (
                            <EmptyState
                                icon={ArchiveRestore}
                                title={
                                    search
                                        ? "Nothing matches that search"
                                        : `No hidden ${current?.module.toLowerCase() ?? "records"}`
                                }
                                description={
                                    search
                                        ? "Try part of a name, a number or an address."
                                        : "This module is empty. Hiding a record puts it here."
                                }
                            />
                        ) : (
                            <ul className="divide-hairline divide-y">
                                {items.data.map((item) => (
                                    <BinRow
                                        key={`${item.key}-${item.id}`}
                                        item={item}
                                        showModule={!current}
                                        open={
                                            expanded ===
                                            `${item.key}-${item.id}`
                                        }
                                        onToggle={() =>
                                            setExpanded(
                                                expanded ===
                                                    `${item.key}-${item.id}`
                                                    ? null
                                                    : `${item.key}-${item.id}`,
                                            )
                                        }
                                        onRestore={() => {
                                            restore.clearErrors();
                                            setPending(item);
                                        }}
                                    />
                                ))}
                            </ul>
                        )}

                        <DataPagination page={items} noun="hidden records" />
                    </TableCard>
                </>
            )}

            <Dialog
                open={pending !== null}
                onOpenChange={(open) => {
                    if (!open) {
                        setPending(null);
                        restore.clearErrors();
                    }
                }}
            >
                <DialogContent className="sm:max-w-md">
                    <DialogHeader>
                        <DialogTitle>Bring this record back?</DialogTitle>
                        <DialogDescription>
                            {pending?.title}
                            {pending?.subtitle ? ` · ${pending.subtitle}` : ""}
                        </DialogDescription>
                    </DialogHeader>

                    <div className="grid gap-3 text-sm">
                        <p className="text-muted-foreground text-xs leading-relaxed">
                            It becomes visible again everywhere it appears, with
                            every field exactly as it was. Nothing else about
                            the record changes.
                        </p>

                        {restore.errors.record ? (
                            <p
                                className="text-danger text-xs font-medium"
                                role="alert"
                            >
                                {restore.errors.record}
                            </p>
                        ) : null}
                    </div>

                    <DialogFooter>
                        <Button
                            type="button"
                            variant="outline"
                            size="sm"
                            onClick={() => setPending(null)}
                        >
                            Cancel
                        </Button>
                        <Button
                            type="button"
                            size="sm"
                            disabled={restore.processing}
                            onClick={confirmRestore}
                        >
                            <RotateCcw className="size-4" />
                            {restore.processing ? "Restoring…" : "Restore"}
                        </Button>
                    </DialogFooter>
                </DialogContent>
            </Dialog>
        </>
    );
}

function CategoryCard({
    label,
    module,
    count,
    tone,
    active,
    onClick,
}: {
    label: string;
    module: string;
    count: number;
    tone: string;
    active: boolean;
    onClick: () => void;
}) {
    const classes = toneClasses(tone);

    return (
        <button
            type="button"
            onClick={onClick}
            aria-pressed={active}
            className={cn(
                "group flex items-center gap-3 rounded-xl px-4 py-3 text-left ring-1 transition",
                active
                    ? "bg-card shadow-card ring-solar/40"
                    : "ring-hairline hover:bg-accent/40 bg-transparent",
            )}
        >
            <span
                className={cn(
                    "flex size-9 shrink-0 items-center justify-center rounded-lg",
                    classes.soft,
                )}
            >
                <Box className="size-4" />
            </span>
            <span className="min-w-0 flex-1">
                <span className="block truncate text-sm font-medium">
                    {label}
                </span>
                <span className="text-muted-foreground block truncate text-[11px]">
                    {module}
                </span>
            </span>
            <span className="crm-num text-lg font-semibold">{count}</span>
        </button>
    );
}

function BinRow({
    item,
    showModule,
    open,
    onToggle,
    onRestore,
}: {
    item: RecycleItem;
    showModule: boolean;
    open: boolean;
    onToggle: () => void;
    onRestore: () => void;
}) {
    return (
        <li className={cn("px-4 py-3", open && "bg-accent/30")}>
            <div className="flex items-start gap-3">
                <span
                    aria-hidden
                    className={cn(
                        "mt-0.5 flex size-8 shrink-0 items-center justify-center rounded-lg",
                        toneClasses(item.tone).soft,
                    )}
                >
                    <Box className="size-4" />
                </span>

                <div className="min-w-0 flex-1">
                    <div className="flex flex-wrap items-center gap-x-2 gap-y-1">
                        <span className="truncate text-sm font-medium">
                            {item.title}
                        </span>
                        {showModule ? (
                            <StatusPill tone={item.tone}>
                                {item.module}
                            </StatusPill>
                        ) : null}
                    </div>

                    <p className="text-muted-foreground mt-0.5 truncate text-[11px]">
                        {item.label}
                        {item.subtitle ? ` · ${item.subtitle}` : ""}
                        {item.deleted_at
                            ? ` · hidden ${formatRelative(item.deleted_at)} by ${item.deleted_by}`
                            : ""}
                    </p>

                    {!item.can_restore && item.blocked_reason ? (
                        <p className="text-warning mt-1 text-[11px] font-medium">
                            {item.blocked_reason}
                        </p>
                    ) : null}
                </div>

                <div className="flex shrink-0 items-center gap-1">
                    <Button
                        type="button"
                        variant="ghost"
                        size="sm"
                        aria-expanded={open}
                        onClick={onToggle}
                        className="text-muted-foreground"
                    >
                        Details
                        <ChevronDown
                            className={cn(
                                "size-3.5 transition-transform",
                                open && "rotate-180",
                            )}
                        />
                    </Button>

                    <Button
                        type="button"
                        variant="outline"
                        size="sm"
                        disabled={!item.can_restore}
                        onClick={onRestore}
                    >
                        <RotateCcw className="size-3.5" />
                        Restore
                    </Button>
                </div>
            </div>

            {open ? (
                <div className="mt-3 ml-11 grid gap-3">
                    <dl className="grid gap-x-6 gap-y-2 sm:grid-cols-2 lg:grid-cols-3">
                        {item.fields.map((field) => (
                            <div key={field.label} className="min-w-0">
                                <dt className="crm-label">{field.label}</dt>
                                <dd className="mt-0.5 text-xs break-words">
                                    {field.value}
                                </dd>
                            </div>
                        ))}
                    </dl>

                    <p className="text-[11px] text-muted-foreground">
                        {item.deleted_at
                            ? `Hidden on ${formatDate(item.deleted_at)}`
                            : "Hidden"}
                        {" · "}
                        {item.deleted_by}
                        {" · Record #"}
                        {item.id}
                    </p>
                </div>
            ) : null}
        </li>
    );
}
