import { Head, router, setLayoutProps } from '@inertiajs/react';
import { Download, RefreshCw, Search, X } from 'lucide-react';
import { useEffect, useMemo, useRef, useState } from 'react';

import {
    download as adminActivitiesDownload,
    index as adminActivitiesIndex,
} from '@/actions/App/Domains/Shared/Http/Controllers/Admin/ActivityLogController';

import { DataPagination } from '@/components/DataPagination';
import { DateFilter, parseIsoDate } from '@/components/DateFilter';
import { Badge } from '@/components/ui/badge';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import {
    Select,
    SelectContent,
    SelectItem,
    SelectTrigger,
    SelectValue,
} from '@/components/ui/select';
import {
    Table,
    TableBody,
    TableCell,
    TableHead,
    TableHeader,
    TableRow,
} from '@/components/ui/table';
import { cn, formatDate } from '@/lib/utils';
import type { AdminActivity, DivisionOption } from '@/types/admin';
import type { PaginationData } from '@/types/pagination';

const FILTER_DEBOUNCE_MS = 300;

const ALL = 'all';

/** `task.status_updated` -> `Task status updated`. */
const humanizeAction = (action: string) =>
    action.replace(/[._]/g, ' ').replace(/^./, (char) => char.toUpperCase());

/** `{ status: ['waiting', 'in_progress'] }` -> `['status: waiting → in_progress']`. */
const describeChanges = (changes: AdminActivity['changes']): string[] =>
    Object.entries(changes ?? {}).map(
        ([field, [before, after]]) =>
            `${field}: ${before ?? '—'} → ${after ?? '—'}`,
    );

interface AdminActivitiesPageProps {
    activities: AdminActivity[];
    pagination: PaginationData;
    filters: {
        search: string;
        division_id: number | null;
        action: string;
        from: string | null;
        to: string | null;
    };
    divisions: DivisionOption[];
    actions: string[];
}

export default function AdminActivitiesIndex({
    activities,
    pagination,
    filters,
    divisions,
    actions,
}: AdminActivitiesPageProps) {
    const [searchQuery, setSearchQuery] = useState(filters.search);
    const [divisionFilter, setDivisionFilter] = useState(
        filters.division_id ? String(filters.division_id) : ALL,
    );
    const [actionFilter, setActionFilter] = useState(filters.action || ALL);
    const [fromDate, setFromDate] = useState(filters.from ?? '');
    const [toDate, setToDate] = useState(filters.to ?? '');

    const [refreshing, setRefreshing] = useState(false);

    const isInitialFilterSync = useRef(true);

    /**
     * Muat ulang isi tabel tanpa memuat ulang halaman.
     *
     * Hanya prop tabel yang diminta ke server; filter, posisi scroll, dan state
     * komponen lain tetap seperti apa adanya. `actions` ikut diminta supaya
     * jenis aksi yang baru pertama kali tercatat langsung muncul di filter.
     */
    const refresh = () =>
        router.reload({
            only: ['activities', 'pagination', 'actions'],
            onStart: () => setRefreshing(true),
            onFinish: () => setRefreshing(false),
        });

    const hasActiveFilters =
        searchQuery !== '' ||
        divisionFilter !== ALL ||
        actionFilter !== ALL ||
        fromDate !== '' ||
        toDate !== '';

    /**
     * Kosongkan seluruh filter sekaligus.
     *
     * Tidak memanggil router sendiri: efek debounce di bawah sudah memantau
     * kelima state ini, jadi perubahannya berangkat sebagai satu request.
     */
    const clearFilters = () => {
        setSearchQuery('');
        setDivisionFilter(ALL);
        setActionFilter(ALL);
        setFromDate('');
        setToDate('');
    };

    // Batas saling kunci antar kedua kalender; undefined berarti tanpa batas.
    const lowerBound = parseIsoDate(fromDate);
    const upperBound = parseIsoDate(toDate);

    // Satu bentuk query dipakai dua kali: memuat ulang tabel dan menyusun URL
    // unduhan, supaya isi CSV selalu sama dengan yang sedang tampil.
    const queryParams = useMemo(
        () => ({
            search: searchQuery || undefined,
            division_id: divisionFilter !== ALL ? divisionFilter : undefined,
            action: actionFilter !== ALL ? actionFilter : undefined,
            from: fromDate || undefined,
            to: toDate || undefined,
        }),
        [searchQuery, divisionFilter, actionFilter, fromDate, toDate],
    );

    useEffect(() => {
        if (isInitialFilterSync.current) {
            isInitialFilterSync.current = false;

            return;
        }

        const request = window.setTimeout(() => {
            router.get(adminActivitiesIndex().url, queryParams, {
                preserveScroll: true,
                preserveState: true,
                replace: true,
            });
        }, FILTER_DEBOUNCE_MS);

        return () => window.clearTimeout(request);
    }, [queryParams]);

    setLayoutProps({
        breadcrumbs: [{ title: 'Activity Log' }],
    });

    return (
        <>
            <Head title="Activity Log" />

            <div className="flex min-h-full flex-col gap-4 p-4 md:p-6">
                <div className="flex flex-col gap-2 sm:flex-row sm:items-center sm:justify-between">
                    <div>
                        <h1 className="text-xl font-bold tracking-tight text-foreground">
                            Activity Log
                        </h1>
                        <p className="text-sm text-muted-foreground">
                            {pagination.total} event
                            {pagination.total === 1 ? '' : 's'} recorded across
                            every division
                        </p>
                    </div>

                    <div className="flex gap-2">
                        <Button
                            variant="outline"
                            className="h-9"
                            disabled={refreshing}
                            onClick={refresh}
                        >
                            <RefreshCw
                                className={cn(
                                    'mr-1 h-4 w-4',
                                    refreshing && 'animate-spin',
                                )}
                            />
                            Refresh
                        </Button>

                        {/* Unduhan mengikuti filter aktif, jadi cukup tautan
                            biasa ke route download tanpa request Inertia. */}
                        <Button variant="outline" className="h-9" asChild>
                            <a
                                href={adminActivitiesDownload.url({
                                    query: queryParams,
                                })}
                            >
                                <Download className="mr-1 h-4 w-4" />
                                Export CSV
                            </a>
                        </Button>
                    </div>
                </div>

                <div className="flex flex-col gap-2 sm:flex-row sm:flex-wrap sm:items-center">
                    <div className="relative w-full sm:w-72">
                        <Search
                            className="absolute top-1/2 left-3 h-4 w-4 -translate-y-1/2 text-muted-foreground"
                            size={16}
                        />
                        <Input
                            placeholder="Search action, actor, or subject..."
                            className="h-9 rounded-lg bg-background pl-9"
                            value={searchQuery}
                            onChange={(e) => setSearchQuery(e.target.value)}
                        />
                    </div>

                    <Select
                        value={divisionFilter}
                        onValueChange={setDivisionFilter}
                    >
                        <SelectTrigger className="h-9 w-full sm:w-44">
                            <SelectValue />
                        </SelectTrigger>
                        <SelectContent>
                            <SelectItem value={ALL}>All divisions</SelectItem>
                            {divisions.map((division) => (
                                <SelectItem
                                    key={division.id}
                                    value={String(division.id)}
                                >
                                    {division.name}
                                </SelectItem>
                            ))}
                        </SelectContent>
                    </Select>

                    <Select
                        value={actionFilter}
                        onValueChange={setActionFilter}
                    >
                        <SelectTrigger className="h-9 w-full sm:w-52">
                            <SelectValue />
                        </SelectTrigger>
                        <SelectContent>
                            <SelectItem value={ALL}>All actions</SelectItem>
                            {actions.map((action) => (
                                <SelectItem key={action} value={action}>
                                    {humanizeAction(action)}
                                </SelectItem>
                            ))}
                        </SelectContent>
                    </Select>

                    {/* Batas rentang saling mengunci: tanggal awal tidak bisa
                        melewati tanggal akhir, dan sebaliknya. */}
                    <div className="flex items-center gap-2">
                        <DateFilter
                            label="From date"
                            value={fromDate}
                            onChange={setFromDate}
                            disabled={upperBound && { after: upperBound }}
                        />
                        <span className="text-sm text-muted-foreground">–</span>
                        <DateFilter
                            label="Until date"
                            value={toDate}
                            onChange={setToDate}
                            disabled={lowerBound && { before: lowerBound }}
                        />
                    </div>

                    {/* Hanya muncul saat ada yang bisa dibersihkan; tombol yang
                        selalu tampil tapi tidak melakukan apa-apa cuma bikin
                        ragu apakah filternya sedang aktif. */}
                    {hasActiveFilters && (
                        <Button
                            variant="ghost"
                            className="h-9 text-muted-foreground"
                            onClick={clearFilters}
                        >
                            <X className="mr-1 h-4 w-4" />
                            Clear filters
                        </Button>
                    )}
                </div>

                <div className="overflow-x-auto rounded-lg border bg-background">
                    <Table>
                        <TableHeader>
                            <TableRow className="hover:bg-transparent">
                                <TableHead className="w-12 text-center">
                                    NO.
                                </TableHead>
                                <TableHead>Activity</TableHead>
                                <TableHead>Performed by</TableHead>
                                <TableHead>Division</TableHead>
                                <TableHead className="w-44">Time</TableHead>
                            </TableRow>
                        </TableHeader>
                        <TableBody>
                            {activities.length === 0 && (
                                <TableRow>
                                    <TableCell
                                        colSpan={5}
                                        className="py-10 text-center text-sm text-muted-foreground"
                                    >
                                        No activity matches the current filter.
                                    </TableCell>
                                </TableRow>
                            )}

                            {activities.map((activity, index) => (
                                <TableRow key={activity.id}>
                                    <TableCell className="text-center text-muted-foreground">
                                        {(pagination.from ?? 0) + index}
                                    </TableCell>

                                    <TableCell>
                                        <div className="flex flex-wrap items-center gap-1">
                                            <Badge
                                                variant="secondary"
                                                className="font-normal"
                                            >
                                                {humanizeAction(
                                                    activity.action,
                                                )}
                                            </Badge>
                                            {activity.subject_label && (
                                                <span className="text-sm font-medium text-foreground">
                                                    {activity.subject_label}
                                                </span>
                                            )}
                                        </div>

                                        {/* Baris hasil backfill membawa kalimat
                                            bebas; baris baru membawa diff. */}
                                        {activity.description && (
                                            <div className="mt-1 text-sm text-muted-foreground">
                                                {activity.description}
                                            </div>
                                        )}
                                        {describeChanges(activity.changes).map(
                                            (change) => (
                                                <div
                                                    key={change}
                                                    className="mt-1 font-mono text-xs text-muted-foreground"
                                                >
                                                    {change}
                                                </div>
                                            ),
                                        )}
                                    </TableCell>

                                    <TableCell className="text-sm text-foreground">
                                        {activity.actor_name ?? (
                                            <span className="text-muted-foreground">
                                                System
                                            </span>
                                        )}
                                    </TableCell>

                                    <TableCell className="text-sm text-muted-foreground">
                                        {activity.division_name ?? '—'}
                                    </TableCell>

                                    <TableCell className="text-sm whitespace-nowrap text-muted-foreground">
                                        {formatDate(activity.created_at, {
                                            withTime: true,
                                        })}
                                    </TableCell>
                                </TableRow>
                            ))}
                        </TableBody>
                    </Table>
                </div>

                <DataPagination
                    pagination={pagination}
                    only={['activities', 'pagination']}
                />
            </div>
        </>
    );
}
