import { Form, Head, router } from '@inertiajs/react';
import { Filter, Plus, X } from 'lucide-react';
import { useCallback, useEffect, useState } from 'react';
import { ConfirmDialog } from '@/components/confirm-dialog';
import { DataTable } from '@/components/data-table';
import type { PaginationState } from '@/components/data-table';
import { DatePicker } from '@/components/date-picker';
import InputError from '@/components/input-error';
import { Button } from '@/components/ui/button';
import {
    Dialog,
    DialogContent,
    DialogFooter,
    DialogHeader,
    DialogTitle,
} from '@/components/ui/dialog';
import { Label } from '@/components/ui/label';
import {
    Popover,
    PopoverContent,
    PopoverTrigger,
} from '@/components/ui/popover';
import {
    Select,
    SelectContent,
    SelectItem,
    SelectTrigger,
    SelectValue,
} from '@/components/ui/select';
import {
    approve,
    destroy,
    index as leaveRequestIndex,
    reject,
    store,
    update,
} from '@/routes/admin/hr/leave-requests';
import type { LeaveRequest } from './columns';
import { createLeaveRequestColumns } from './columns';

type Props = {
    leaveRequests: {
        data: LeaveRequest[];
        current_page: number;
        last_page: number;
        per_page: number;
        total: number;
    };
    filters: {
        status?: string;
    };
};

export default function LeaveRequestIndex({ leaveRequests, filters }: Props) {
    const [createOpen, setCreateOpen] = useState(false);
    const [editing, setEditing] = useState<LeaveRequest | null>(null);
    const [deleting, setDeleting] = useState<LeaveRequest | null>(null);
    const [approving, setApproving] = useState<LeaveRequest | null>(null);
    const [rejecting, setRejecting] = useState<LeaveRequest | null>(null);
    const [startDate, setStartDate] = useState<Date | undefined>(undefined);
    const [endDate, setEndDate] = useState<Date | undefined>(undefined);
    const [editingStartDate, setEditingStartDate] = useState<Date | undefined>(
        undefined,
    );
    const [editingEndDate, setEditingEndDate] = useState<Date | undefined>(
        undefined,
    );
    const [filterOpen, setFilterOpen] = useState(false);
    const [search, setSearch] = useState('');
    const pagination: PaginationState = {
        current_page: leaveRequests.current_page,
        last_page: leaveRequests.last_page,
        per_page: leaveRequests.per_page,
        total: leaveRequests.total,
    };

    const hasActiveFilters = filters.status;

    useEffect(() => {
        if (editing) {
            setEditingStartDate(new Date(editing.start_date));
            setEditingEndDate(new Date(editing.end_date));
        } else {
            setEditingStartDate(undefined);
            setEditingEndDate(undefined);
        }
    }, [editing]);

    function applyFilter(key: string, value: string) {
        const newFilters = { ...filters };

        if (value === '' || value === 'all') {
            delete newFilters[key as keyof typeof newFilters];
        } else {
            newFilters[key as keyof typeof newFilters] = value;
        }

        router.get(
            leaveRequestIndex(),
            {
                ...newFilters,
                page: 1,
                per_page: pagination.per_page,
                search,
            },
            { preserveState: true, replace: true },
        );
    }

    function clearFilters() {
        router.get(
            leaveRequestIndex(),
            {
                page: 1,
                per_page: pagination.per_page,
                search,
            },
            { preserveState: true, replace: true },
        );
        setFilterOpen(false);
    }

    function handleDelete() {
        if (!deleting) {
            return;
        }

        router.delete(destroy(deleting.id), {
            onSuccess: () => setDeleting(null),
        });
    }

    function handleApprove() {
        if (!approving) {
            return;
        }

        router.post(
            approve(approving.id),
            {},
            {
                onSuccess: () => setApproving(null),
            },
        );
    }

    function handleReject() {
        if (!rejecting) {
            return;
        }

        router.post(
            reject(rejecting.id),
            {},
            {
                onSuccess: () => setRejecting(null),
            },
        );
    }

    function handlePageChange(page: number) {
        router.get(
            leaveRequestIndex(),
            {
                ...filters,
                page,
                per_page: pagination.per_page,
                search,
            },
            { preserveState: true, replace: true },
        );
    }

    function handlePerPageChange(perPage: number) {
        router.get(
            leaveRequestIndex(),
            {
                ...filters,
                page: 1,
                per_page: perPage,
                search,
            },
            { preserveState: true, replace: true },
        );
    }

    const handleSearchChange = useCallback(
        (value: string) => {
            setSearch(value);
            router.get(
                leaveRequestIndex(),
                {
                    ...filters,
                    page: 1,
                    per_page: pagination.per_page,
                    search: value,
                },
                { preserveState: true, replace: true },
            );
        },
        [pagination.per_page, filters],
    );

    const columns = createLeaveRequestColumns({
        handleEdit: (leaveRequest) => setEditing(leaveRequest),
        handleDeleteClick: (leaveRequest) => setDeleting(leaveRequest),
        handleApprove: (leaveRequest) => setApproving(leaveRequest),
        handleReject: (leaveRequest) => setRejecting(leaveRequest),
    });

    const filterToolbar = (
        <Popover open={filterOpen} onOpenChange={setFilterOpen}>
            <PopoverTrigger asChild>
                <Button variant="outline" size="sm">
                    <Filter className="h-4 w-4" />
                    Filter
                    {hasActiveFilters && (
                        <span className="ml-1 flex h-5 w-5 items-center justify-center rounded-full bg-primary text-xs text-primary-foreground">
                            {Object.values(filters).filter(Boolean).length}
                        </span>
                    )}
                </Button>
            </PopoverTrigger>
            <PopoverContent className="w-64" align="end">
                <div className="flex flex-col gap-4">
                    <div className="flex items-center justify-between">
                        <span className="text-sm font-medium">Filter</span>
                        {hasActiveFilters && (
                            <Button
                                variant="ghost"
                                size="sm"
                                className="h-6 px-2 text-xs"
                                onClick={clearFilters}
                            >
                                <X className="mr-1 h-3 w-3" />
                                Hapus Semua
                            </Button>
                        )}
                    </div>

                    <div className="flex flex-col gap-2">
                        <label className="text-xs text-muted-foreground">
                            Status
                        </label>
                        <Select
                            value={filters.status ?? 'all'}
                            onValueChange={(value) =>
                                applyFilter('status', value)
                            }
                        >
                            <SelectTrigger className="w-full">
                                <SelectValue placeholder="Semua Status" />
                            </SelectTrigger>
                            <SelectContent>
                                <SelectItem value="all">
                                    Semua Status
                                </SelectItem>
                                <SelectItem value="pending">
                                    Menunggu
                                </SelectItem>
                                <SelectItem value="approved">
                                    Disetujui
                                </SelectItem>
                                <SelectItem value="rejected">
                                    Ditolak
                                </SelectItem>
                                <SelectItem value="cancelled">
                                    Dibatalkan
                                </SelectItem>
                            </SelectContent>
                        </Select>
                    </div>
                </div>
            </PopoverContent>
        </Popover>
    );

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

            <div className="flex h-full flex-1 flex-col gap-6 overflow-x-auto p-4 md:p-6">
                <div className="flex items-center justify-between">
                    <div>
                        <h2 className="text-2xl font-semibold tracking-tight">
                            Cuti
                        </h2>
                    </div>
                    <Dialog
                        open={createOpen}
                        onOpenChange={(open) => {
                            setCreateOpen(open);

                            if (!open) {
                                setStartDate(undefined);
                                setEndDate(undefined);
                            }
                        }}
                    >
                        <Button asChild>
                            <button
                                type="button"
                                onClick={() => setCreateOpen(true)}
                            >
                                <Plus className="h-4 w-4" />
                                Tambah
                            </button>
                        </Button>
                        <DialogContent>
                            <Form
                                action={store()}
                                resetOnSuccess
                                onSuccess={() => setCreateOpen(false)}
                            >
                                {({ errors, processing }) => {
                                    return (
                                        <>
                                            <DialogHeader>
                                                <DialogTitle>
                                                    Tambah Permohonan Cuti
                                                </DialogTitle>
                                            </DialogHeader>
                                            <div className="grid gap-4 py-4">
                                                <div className="grid gap-2">
                                                    <Label>
                                                        Tanggal Mulai{' '}
                                                        <span className="text-destructive">
                                                            *
                                                        </span>
                                                    </Label>
                                                    <input
                                                        type="hidden"
                                                        name="start_date"
                                                        value={
                                                            startDate
                                                                ? startDate
                                                                      .toISOString()
                                                                      .split(
                                                                          'T',
                                                                      )[0]
                                                                : ''
                                                        }
                                                    />
                                                    <DatePicker
                                                        value={startDate}
                                                        onChange={setStartDate}
                                                        placeholder="Pilih tanggal mulai"
                                                        min={new Date()}
                                                    />
                                                    <InputError
                                                        message={
                                                            errors.start_date
                                                        }
                                                    />
                                                </div>
                                                <div className="grid gap-2">
                                                    <Label>
                                                        Tanggal Selesai{' '}
                                                        <span className="text-destructive">
                                                            *
                                                        </span>
                                                    </Label>
                                                    <input
                                                        type="hidden"
                                                        name="end_date"
                                                        value={
                                                            endDate
                                                                ? endDate
                                                                      .toISOString()
                                                                      .split(
                                                                          'T',
                                                                      )[0]
                                                                : ''
                                                        }
                                                    />
                                                    <DatePicker
                                                        value={endDate}
                                                        onChange={setEndDate}
                                                        placeholder="Pilih tanggal selesai"
                                                        min={startDate}
                                                    />
                                                    <InputError
                                                        message={
                                                            errors.end_date
                                                        }
                                                    />
                                                </div>
                                            </div>
                                            <DialogFooter>
                                                <Button
                                                    type="button"
                                                    variant="outline"
                                                    onClick={() =>
                                                        setCreateOpen(false)
                                                    }
                                                >
                                                    Batal
                                                </Button>
                                                <Button
                                                    type="submit"
                                                    disabled={processing}
                                                >
                                                    {processing
                                                        ? 'Menyimpan...'
                                                        : 'Simpan'}
                                                </Button>
                                            </DialogFooter>
                                        </>
                                    );
                                }}
                            </Form>
                        </DialogContent>
                    </Dialog>
                </div>

                <DataTable
                    columns={columns}
                    data={leaveRequests.data}
                    searchKey="employee.user.user_profile.full_name"
                    searchPlaceholder="Cari nama karyawan..."
                    emptyText="Belum ada data permohonan cuti."
                    pagination={pagination}
                    onPageChange={handlePageChange}
                    onPerPageChange={handlePerPageChange}
                    onSearchChange={handleSearchChange}
                    searchValue={search}
                    toolbar={filterToolbar}
                />

                <Dialog
                    open={editing !== null}
                    onOpenChange={(open) => {
                        if (!open) {
                            setEditing(null);
                            setEditingStartDate(undefined);
                            setEditingEndDate(undefined);
                        }
                    }}
                >
                    <DialogContent>
                        {editing && (
                            <Form
                                action={update(editing.id)}
                                resetOnSuccess
                                onSuccess={() => {
                                    setEditing(null);
                                    setEditingStartDate(undefined);
                                    setEditingEndDate(undefined);
                                }}
                            >
                                {({ errors, processing }) => {
                                    return (
                                        <>
                                            <DialogHeader>
                                                <DialogTitle>
                                                    Edit Permohonan Cuti
                                                </DialogTitle>
                                            </DialogHeader>
                                            <div className="grid gap-4 py-4">
                                                <div className="grid gap-2">
                                                    <Label>
                                                        Tanggal Mulai{' '}
                                                        <span className="text-destructive">
                                                            *
                                                        </span>
                                                    </Label>
                                                    <input
                                                        type="hidden"
                                                        name="start_date"
                                                        value={
                                                            editingStartDate
                                                                ? editingStartDate
                                                                      .toISOString()
                                                                      .split(
                                                                          'T',
                                                                      )[0]
                                                                : ''
                                                        }
                                                    />
                                                    <DatePicker
                                                        value={editingStartDate}
                                                        onChange={
                                                            setEditingStartDate
                                                        }
                                                        placeholder="Pilih tanggal mulai"
                                                        min={new Date()}
                                                    />
                                                    <InputError
                                                        message={
                                                            errors.start_date
                                                        }
                                                    />
                                                </div>
                                                <div className="grid gap-2">
                                                    <Label>
                                                        Tanggal Selesai{' '}
                                                        <span className="text-destructive">
                                                            *
                                                        </span>
                                                    </Label>
                                                    <input
                                                        type="hidden"
                                                        name="end_date"
                                                        value={
                                                            editingEndDate
                                                                ? editingEndDate
                                                                      .toISOString()
                                                                      .split(
                                                                          'T',
                                                                      )[0]
                                                                : ''
                                                        }
                                                    />
                                                    <DatePicker
                                                        value={editingEndDate}
                                                        onChange={
                                                            setEditingEndDate
                                                        }
                                                        placeholder="Pilih tanggal selesai"
                                                        min={editingStartDate}
                                                    />
                                                    <InputError
                                                        message={
                                                            errors.end_date
                                                        }
                                                    />
                                                </div>
                                            </div>
                                            <DialogFooter>
                                                <Button
                                                    type="button"
                                                    variant="outline"
                                                    onClick={() => {
                                                        setEditing(null);
                                                    }}
                                                >
                                                    Batal
                                                </Button>
                                                <Button
                                                    type="submit"
                                                    disabled={processing}
                                                >
                                                    {processing
                                                        ? 'Menyimpan...'
                                                        : 'Simpan'}
                                                </Button>
                                            </DialogFooter>
                                        </>
                                    );
                                }}
                            </Form>
                        )}
                    </DialogContent>
                </Dialog>

                <ConfirmDialog
                    open={deleting !== null}
                    onOpenChange={(open) => {
                        if (!open) {
                            setDeleting(null);
                        }
                    }}
                    title="Hapus Permohonan Cuti"
                    description={`Apakah Anda yakin ingin menghapus permohonan cuti ini? Tindakan ini tidak dapat dibatalkan.`}
                    confirmLabel="Hapus"
                    onConfirm={handleDelete}
                />

                <ConfirmDialog
                    open={approving !== null}
                    onOpenChange={(open) => {
                        if (!open) {
                            setApproving(null);
                        }
                    }}
                    title="Setujui Permohonan Cuti"
                    description={`Apakah Anda yakin ingin menyetujui permohonan cuti ini?`}
                    confirmLabel="Setujui"
                    onConfirm={handleApprove}
                />

                <ConfirmDialog
                    open={rejecting !== null}
                    onOpenChange={(open) => {
                        if (!open) {
                            setRejecting(null);
                        }
                    }}
                    title="Tolak Permohonan Cuti"
                    description={`Apakah Anda yakin ingin menolak permohonan cuti ini?`}
                    confirmLabel="Tolak"
                    onConfirm={handleReject}
                />
            </div>
        </>
    );
}
