import { Head, router } from '@inertiajs/react';
import { useState } from 'react';

import HeadingSmall from '@/components/heading-small';
import { SortableHeader, useSort } from '@/components/sortable-header';
import {
    Dialog,
    DialogContent,
    DialogDescription,
    DialogFooter,
    DialogHeader,
    DialogTitle,
} from '@/components/ui/dialog';
import { useUserTimezone } from '@/hooks/use-user-timezone';
import AppLayout from '@/layouts/app-layout';
import { formatDateTime } from '@/lib/format-date';
import backups from '@/routes/admin/backups';

type Backup = {
    disk: string;
    path: string;
    filename: string;
    size_bytes: number;
    size_human: string;
    date: string;
};

type Props = {
    backups: Backup[];
    disks: string[];
};

const breadcrumbs = [{ title: 'Backups', href: backups.index.url() }];

export default function Backups({ backups: backupList, disks }: Props) {
    const timezone = useUserTimezone();
    const { sorted, sortColumn, sortDirection, toggleSort } = useSort(backupList, 'date', 'desc');
    const [pendingDelete, setPendingDelete] = useState<Backup | null>(null);
    const [deleting, setDeleting] = useState(false);

    const totalBytes = backupList.reduce((sum, b) => sum + b.size_bytes, 0);

    function confirmDelete() {
        if (!pendingDelete) return;

        setDeleting(true);
        router.delete(backups.destroy.url({ query: { disk: pendingDelete.disk, path: pendingDelete.path } }), {
            preserveScroll: true,
            onFinish: () => {
                setDeleting(false);
                setPendingDelete(null);
            },
        });
    }

    return (
        <AppLayout breadcrumbs={breadcrumbs}>
            <Head title="Backups" />

            <h1 className="sr-only">Backups</h1>

            <div className="space-y-6">
                <div className="flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between">
                    <HeadingSmall
                        title="Backups"
                        description={`${backupList.length} backup${backupList.length === 1 ? '' : 's'} across ${disks.length} disk${disks.length === 1 ? '' : 's'} (${totalBytesLabel(totalBytes)} total)`}
                    />
                </div>

                <div className="overflow-hidden rounded-md border border-zinc-200 bg-white dark:border-zinc-800 dark:bg-zinc-950">
                    <div className="overflow-x-auto">
                        <table className="w-full text-left text-sm">
                            <thead className="border-b border-zinc-200 text-xs uppercase text-zinc-600 dark:border-zinc-800 dark:text-zinc-400">
                                <tr>
                                    <SortableHeader label="Filename" column="filename" sortColumn={sortColumn} sortDirection={sortDirection} onSort={toggleSort} />
                                    <SortableHeader label="Disk" column="disk" sortColumn={sortColumn} sortDirection={sortDirection} onSort={toggleSort} />
                                    <SortableHeader label="Size" column="size_bytes" sortColumn={sortColumn} sortDirection={sortDirection} onSort={toggleSort} />
                                    <SortableHeader label="Created" column="date" sortColumn={sortColumn} sortDirection={sortDirection} onSort={toggleSort} />
                                    <th className="px-4 py-3 text-right">Actions</th>
                                </tr>
                            </thead>
                            <tbody className="divide-y divide-zinc-200 dark:divide-zinc-800">
                                {sorted.map((backup) => (
                                    <tr key={`${backup.disk}:${backup.path}`}>
                                        <td className="px-4 py-3 font-mono text-xs text-zinc-700 dark:text-zinc-300">
                                            {backup.filename}
                                        </td>
                                        <td className="px-4 py-3 text-zinc-600 dark:text-zinc-400">{backup.disk}</td>
                                        <td className="px-4 py-3 text-zinc-600 dark:text-zinc-400">{backup.size_human}</td>
                                        <td className="px-4 py-3 text-zinc-600 dark:text-zinc-400">
                                            {formatDateTime(backup.date, timezone)}
                                        </td>
                                        <td className="px-4 py-3">
                                            <div className="flex items-center justify-end gap-3">
                                                <a
                                                    href={backups.download.url({ query: { disk: backup.disk, path: backup.path } })}
                                                    className="text-sm text-blue-700 hover:underline dark:text-blue-400"
                                                >
                                                    Download
                                                </a>
                                                <button
                                                    type="button"
                                                    onClick={() => setPendingDelete(backup)}
                                                    className="text-sm text-red-700 hover:underline dark:text-red-400"
                                                >
                                                    Delete
                                                </button>
                                            </div>
                                        </td>
                                    </tr>
                                ))}
                            </tbody>
                        </table>
                    </div>

                    {backupList.length === 0 && (
                        <div className="p-4 text-sm text-zinc-600 dark:text-zinc-400">
                            No backups found.
                        </div>
                    )}
                </div>
            </div>

            <Dialog open={pendingDelete !== null} onOpenChange={(open) => { if (!open) setPendingDelete(null); }}>
                <DialogContent className="sm:max-w-md">
                    <DialogHeader>
                        <DialogTitle>Delete backup</DialogTitle>
                        <DialogDescription>
                            This will permanently delete{' '}
                            <span className="font-mono text-xs">{pendingDelete?.filename}</span> from the{' '}
                            {pendingDelete?.disk} disk. This cannot be undone.
                        </DialogDescription>
                    </DialogHeader>

                    <DialogFooter>
                        <button
                            type="button"
                            onClick={() => setPendingDelete(null)}
                            className="rounded-md px-3 py-2 text-sm font-medium text-zinc-600 hover:text-zinc-900 dark:text-zinc-400 dark:hover:text-zinc-100"
                        >
                            Cancel
                        </button>
                        <button
                            type="button"
                            disabled={deleting}
                            onClick={confirmDelete}
                            className="rounded-md bg-red-600 px-3 py-2 text-sm font-medium text-white disabled:opacity-60"
                        >
                            {deleting ? 'Deleting…' : 'Delete'}
                        </button>
                    </DialogFooter>
                </DialogContent>
            </Dialog>
        </AppLayout>
    );
}

function totalBytesLabel(bytes: number): string {
    if (bytes === 0) return '0 B';
    const units = ['B', 'KB', 'MB', 'GB', 'TB'];
    const exponent = Math.min(Math.floor(Math.log(bytes) / Math.log(1024)), units.length - 1);
    const value = bytes / 1024 ** exponent;
    return `${value.toFixed(1)} ${units[exponent]}`;
}
