import { Head, router } from '@inertiajs/react';
import { format } from 'date-fns';
import { Download } from 'lucide-react';
import { useState } from 'react';
import type { PaginationState } from '@/components/data-table';
import { DataTable } from '@/components/data-table';
import type { FilterField } from '@/components/filter-dialog';
import { FilterDialog } from '@/components/filter-dialog';
import { PageHeader } from '@/components/page-header';
import { Badge } from '@/components/ui/badge';
import { Button } from '@/components/ui/button';
import {
    Dialog,
    DialogContent,
    DialogDescription,
    DialogHeader,
    DialogTitle,
} from '@/components/ui/dialog';
import {
    Select,
    SelectContent,
    SelectItem,
    SelectTrigger,
    SelectValue,
} from '@/components/ui/select';
import { useServerTable } from '@/hooks/use-server-table';
import { index as logsIndex, download } from '@/routes/admin/developer/logs';
import type { LogEntry, LogFile } from '@/types/log-entry';
import { LogLevels } from '@/types/log-entry';
import { createLogColumns } from './columns';

type Props = {
    entries: {
        data: LogEntry[];
        current_page: number;
        last_page: number;
        per_page: number;
        total: number;
    } | null;
    files: LogFile[];
    selectedFile: string | null;
    filters: {
        file?: string;
        level?: string;
    };
};

function formatFileSize(bytes: number): string {
    if (bytes < 1024) {
        return `${bytes} B`;
    }

    if (bytes < 1024 * 1024) {
        return `${(bytes / 1024).toFixed(1)} KB`;
    }

    return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
}

export default function LogIndex({
    entries,
    files,
    selectedFile,
    filters,
}: Props) {
    const [detail, setDetail] = useState<LogEntry | null>(null);

    const filterFields: FilterField[] = [
        {
            key: 'level',
            label: 'Level',
            options: LogLevels.map((level) => ({
                value: level,
                label: level,
            })),
        },
    ];

    const pagination: PaginationState = {
        current_page: entries?.current_page ?? 1,
        last_page: entries?.last_page ?? 1,
        per_page: entries?.per_page ?? 25,
        total: entries?.total ?? 0,
    };

    const {
        search,
        handlePageChange,
        handlePerPageChange,
        handleSearchChange,
        applyFilters,
    } = useServerTable({
        route: () => logsIndex.url(),
        pagination,
        filters,
    });

    function handleFileChange(file: string) {
        router.get(
            logsIndex.url(),
            { file, level: filters.level },
            { preserveState: true, replace: true },
        );
    }

    const columns = createLogColumns({
        handleViewDetail: (entry) => setDetail(entry),
    });

    return (
        <>
            <Head title="Logs" />

            <div className="flex h-full flex-1 flex-col gap-6 overflow-x-auto p-4 md:p-6">
                <PageHeader
                    title="Logs"
                    actions={
                        selectedFile && (
                            <Button variant="outline" asChild>
                                <a
                                    href={download.url({
                                        query: { file: selectedFile },
                                    })}
                                >
                                    <Download className="h-4 w-4" />
                                    Unduh
                                </a>
                            </Button>
                        )
                    }
                />

                <div className="flex flex-wrap items-center gap-3">
                    <Select
                        value={selectedFile ?? undefined}
                        onValueChange={handleFileChange}
                    >
                        <SelectTrigger className="w-full sm:w-80">
                            <SelectValue placeholder="Pilih file log" />
                        </SelectTrigger>
                        <SelectContent>
                            {files.map((file) => (
                                <SelectItem key={file.name} value={file.name}>
                                    {file.name} &middot;{' '}
                                    {formatFileSize(file.size)}
                                </SelectItem>
                            ))}
                        </SelectContent>
                    </Select>
                </div>

                {entries ? (
                    <DataTable
                        columns={columns}
                        data={entries.data}
                        pagination={pagination}
                        onPageChange={handlePageChange}
                        onPerPageChange={handlePerPageChange}
                        onSearchChange={handleSearchChange}
                        searchValue={search}
                        searchKey="message"
                        searchPlaceholder="Cari pesan log..."
                        emptyText="Tidak ada entri log yang cocok."
                        toolbar={
                            <FilterDialog
                                fields={filterFields}
                                activeFilters={filters}
                                onApply={applyFilters}
                            />
                        }
                    />
                ) : (
                    <p className="text-sm text-muted-foreground">
                        Belum ada file log yang tersedia.
                    </p>
                )}

                <Dialog
                    open={detail !== null}
                    onOpenChange={(open) => {
                        if (!open) {
                            setDetail(null);
                        }
                    }}
                >
                    <DialogContent className="flex max-h-[85vh] flex-col overflow-hidden sm:max-w-3xl">
                        <DialogHeader>
                            <DialogTitle className="flex items-center gap-2">
                                {detail?.level && (
                                    <Badge variant="outline">
                                        {detail.level}
                                    </Badge>
                                )}
                                <span>Detail Log</span>
                            </DialogTitle>
                            <DialogDescription>
                                {detail &&
                                    !Number.isNaN(
                                        new Date(
                                            detail.timestamp.replace(' ', 'T'),
                                        ).getTime(),
                                    ) &&
                                    format(
                                        new Date(
                                            detail.timestamp.replace(' ', 'T'),
                                        ),
                                        'd MMM yyyy, HH:mm:ss',
                                    )}
                            </DialogDescription>
                        </DialogHeader>
                        <pre className="overflow-y-auto rounded-md bg-muted p-3 font-mono text-xs break-all whitespace-pre-wrap">
                            {detail?.raw}
                        </pre>
                    </DialogContent>
                </Dialog>
            </div>
        </>
    );
}
