import { Head, router, setLayoutProps } from '@inertiajs/react';
import {
    AlertCircle,
    CheckSquare,
    NotebookPen,
    Search,
    SlidersHorizontal,
} from 'lucide-react';
import {
    useCallback,
    useEffect,
    useRef,
    useState,
    useSyncExternalStore,
} from 'react';
import { toast } from 'sonner';

import { ConfirmDeleteDialog } from '@/components/ConfirmDeleteDialog';
import { DataPagination } from '@/components/DataPagination';
import { MyTaskDetailSheet } from '@/components/my-tasks/MyTaskDetailSheet';
import { MyTaskFormSheet } from '@/components/my-tasks/MyTaskFormSheet';
import { MyTasksTable } from '@/components/my-tasks/MyTasksTable';
import { Badge } from '@/components/ui/badge';
import { Button } from '@/components/ui/button';
import {
    DropdownMenu,
    DropdownMenuContent,
    DropdownMenuLabel,
    DropdownMenuRadioGroup,
    DropdownMenuRadioItem,
    DropdownMenuSeparator,
    DropdownMenuTrigger,
} from '@/components/ui/dropdown-menu';
import { Input } from '@/components/ui/input';
import { HEADING_CLASS } from '@/lib/typography';
import { hasOpenOverlay, isTypingTarget } from '@/lib/utils';
import { destroy, index as personalTasksIndex } from '@/routes/personal-tasks';
import type { MyTask, MyTasksPageProps } from '@/types/my-task';

const FILTER_DEBOUNCE_MS = 300;

/** Modifier tidak pernah berubah selama sesi, jadi tidak ada yang perlu dilanggan. */
function subscribeToNothing() {
    return () => {};
}

function getShortcutModifier() {
    return navigator.platform.toUpperCase().includes('MAC') ? '⌘' : 'Ctrl ';
}

function getServerShortcutModifier() {
    return 'Ctrl ';
}

export default function MyTasksIndex({
    tasks,
    pagination,
    filters,
    summary,
}: MyTasksPageProps) {
    const [searchQuery, setSearchQuery] = useState(filters.search);
    const [statusFilter, setStatusFilter] = useState(filters.status);
    const [sortBy, setSortBy] = useState(filters.sort);

    const [isCreateSheetOpen, setIsCreateSheetOpen] = useState(false);
    const [viewingTaskId, setViewingTaskId] = useState<number | null>(null);
    const [editingTask, setEditingTask] = useState<MyTask | null>(null);
    const [subtaskParentId, setSubtaskParentId] = useState<number | null>(null);
    const [deletingTask, setDeletingTask] = useState<MyTask | null>(null);
    const [processingDelete, setProcessingDelete] = useState(false);

    const searchInputRef = useRef<HTMLInputElement>(null);

    // Dibaca lewat useSyncExternalStore agar render server memakai snapshot
    // netral ('Ctrl ') dan klien memakai modifier sesuai OS, tanpa memicu
    // render berantai seperti pola setState-di-dalam-effect.
    const shortcutModifier = useSyncExternalStore(
        subscribeToNothing,
        getShortcutModifier,
        getServerShortcutModifier,
    );

    // Server memangkas spasi pinggir sebelum mencari dan memulangkan nilai yang
    // sudah terpangkas, jadi yang dibandingkan di bawah harus terpangkas juga.
    const trimmedSearch = searchQuery.trim();

    /**
     * Penjaga efek: apakah state lokal masih berbeda dari yang dipegang server.
     *
     * Menggantikan flag "sudah mount". Aplikasi berjalan dengan `strictMode`
     * (lihat app.tsx), jadi efeknya dijalankan dua kali saat mount: jalan
     * pertama mematikan flag lalu keluar, dan jalan kedua justru lolos karena
     * flag-nya sudah mati — menembakkan satu request palsu 300ms kemudian.
     * Request itu membawa `replace: true`, jadi ia menimpa navigasi apa pun yang
     * sedang berjalan: klik ke halaman lain tepat setelah halaman ini terbuka
     * terlempar balik ke sini. Sama seperti penjaga di useRecurringTasksFilters.
     */
    const filtersChanged =
        trimmedSearch !== filters.search ||
        statusFilter !== filters.status ||
        sortBy !== filters.sort;

    useEffect(() => {
        if (!filtersChanged) {
            return;
        }

        const request = window.setTimeout(() => {
            router.get(
                personalTasksIndex().url,
                {
                    search: trimmedSearch || undefined,
                    status: statusFilter !== 'all' ? statusFilter : undefined,
                    sort: sortBy !== 'default' ? sortBy : undefined,
                },
                { preserveScroll: true, preserveState: true, replace: true },
            );
        }, FILTER_DEBOUNCE_MS);

        return () => window.clearTimeout(request);
    }, [filtersChanged, trimmedSearch, statusFilter, sortBy]);

    const openCreateSheet = useCallback(() => {
        setSubtaskParentId(null);
        setIsCreateSheetOpen(true);
    }, []);

    useEffect(() => {
        const handleShortcut = (event: KeyboardEvent) => {
            // Selama ada sheet/dialog terbuka, pintasan halaman ini diam
            // seluruhnya. Keduanya bekerja pada halaman di belakang overlay:
            // "n" pernah membuka sheet task baru di atas sheet detail yang
            // sedang dibaca, dan Ctrl+K menarik fokus ke kolom cari yang
            // tertutup — hanya untuk direbut kembali oleh jebakan fokus overlay.
            if (hasOpenOverlay()) {
                return;
            }

            const key = event.key.toLowerCase();

            if (key === 'k' && (event.metaKey || event.ctrlKey)) {
                event.preventDefault();
                searchInputRef.current?.focus();

                return;
            }

            // Shortcut huruf tunggal hanya berlaku di luar field input dan
            // tanpa modifier, agar tidak menabrak shortcut bawaan browser.
            if (
                key === 'n' &&
                !event.metaKey &&
                !event.ctrlKey &&
                !event.altKey &&
                !isTypingTarget(event.target)
            ) {
                event.preventDefault();
                openCreateSheet();
            }
        };

        window.addEventListener('keydown', handleShortcut);

        return () => window.removeEventListener('keydown', handleShortcut);
    }, [openCreateSheet]);

    // Task yang sedang dilihat bisa berupa root task ATAU subtask ter-nest,
    // jadi pencariannya harus mencakup keduanya.
    const viewingTask = viewingTaskId
        ? (tasks.find((t) => t.id === viewingTaskId) ??
          tasks
              .flatMap((t) => t.subtasks ?? [])
              .find((sub) => sub.id === viewingTaskId) ??
          null)
        : null;

    // Subtask perlu tahu status induknya: server menolak subtask yang jalan
    // sebelum induknya jalan, dan kedua panel memakai keadaan yang sama untuk
    // mematikan pilihannya alih-alih membiarkan pengguna menabrak error.
    const parentStatusOf = (task: MyTask | null) =>
        task?.parent_id != null
            ? (tasks.find((t) => t.id === task.parent_id)?.status ?? null)
            : null;

    const handleDelete = () => {
        if (!deletingTask) {
            return;
        }

        router.delete(destroy(deletingTask.id).url, {
            preserveScroll: true,
            onBefore: () => setProcessingDelete(true),
            onFinish: () => setProcessingDelete(false),
            onSuccess: () => {
                toast.success('Task deleted');
                setDeletingTask(null);
            },
            onError: () => toast.error('Failed to delete task'),
        });
    };

    const hasActiveFilters =
        searchQuery !== '' || statusFilter !== 'all' || sortBy !== 'default';

    const clearFilters = () => {
        setSearchQuery('');
        setStatusFilter('all');
        setSortBy('default');
    };

    setLayoutProps({
        breadcrumbs: [{ title: 'My Tasks' }],
    });

    return (
        <>
            <Head title="My Tasks" />

            <div className="flex flex-col gap-8 p-6 lg:p-8">
                <section className="space-y-4">
                    <div className="flex flex-col gap-4">
                        <div className="flex items-center gap-2">
                            <NotebookPen className="text-primary" size={22} />
                            <h1 className={HEADING_CLASS.section}>My Tasks</h1>
                            {summary.overdue > 0 && (
                                <Badge
                                    variant="outline"
                                    className="border-red-500/30 text-red-600 dark:text-red-400"
                                >
                                    {summary.overdue} overdue
                                </Badge>
                            )}
                        </div>

                        <div className="flex flex-col gap-2 md:flex-row md:items-center md:justify-between">
                            <div className="relative w-full md:max-w-sm">
                                <Search
                                    className="absolute top-1/2 left-3 h-4 w-4 -translate-y-1/2 text-muted-foreground"
                                    size={16}
                                />
                                <Input
                                    ref={searchInputRef}
                                    placeholder="Search tasks..."
                                    className="h-9 rounded-lg pr-12 pl-9"
                                    value={searchQuery}
                                    onChange={(e) =>
                                        setSearchQuery(e.target.value)
                                    }
                                />
                                <kbd className="pointer-events-none absolute top-1/2 right-3 hidden -translate-y-1/2 items-center gap-0.5 rounded border bg-muted px-1.5 font-mono text-[10px] font-medium text-muted-foreground select-none sm:inline-flex">
                                    {shortcutModifier}K
                                </kbd>
                            </div>

                            <div className="flex items-center gap-2">
                                <DropdownMenu>
                                    <DropdownMenuTrigger asChild>
                                        <Button
                                            variant="outline"
                                            className="h-9 gap-2 rounded-lg"
                                        >
                                            <SlidersHorizontal size={16} />
                                            <span className="hidden sm:inline">
                                                Filters
                                            </span>
                                        </Button>
                                    </DropdownMenuTrigger>
                                    <DropdownMenuContent
                                        align="end"
                                        className="w-56"
                                    >
                                        <DropdownMenuLabel className="text-[10px] font-bold tracking-wider text-muted-foreground uppercase">
                                            Filter by Status
                                        </DropdownMenuLabel>
                                        <DropdownMenuRadioGroup
                                            value={statusFilter}
                                            onValueChange={setStatusFilter}
                                        >
                                            <DropdownMenuRadioItem value="all">
                                                All Status
                                            </DropdownMenuRadioItem>
                                            <DropdownMenuRadioItem value="todo">
                                                To Do
                                            </DropdownMenuRadioItem>
                                            <DropdownMenuRadioItem value="in_progress">
                                                In Progress
                                            </DropdownMenuRadioItem>
                                            <DropdownMenuRadioItem value="done">
                                                Done
                                            </DropdownMenuRadioItem>
                                        </DropdownMenuRadioGroup>

                                        <DropdownMenuSeparator />

                                        <DropdownMenuLabel className="text-[10px] font-bold tracking-wider text-muted-foreground uppercase">
                                            Sort by
                                        </DropdownMenuLabel>
                                        <DropdownMenuRadioGroup
                                            value={sortBy}
                                            onValueChange={setSortBy}
                                        >
                                            {/* Bukan "My Order": tidak ada
                                                pengurutan manual: urutannya
                                                mengikuti waktu pembuatan. */}
                                            <DropdownMenuRadioItem value="default">
                                                Default
                                            </DropdownMenuRadioItem>
                                            <DropdownMenuRadioItem value="newest">
                                                Newest
                                            </DropdownMenuRadioItem>
                                            <DropdownMenuRadioItem value="oldest">
                                                Oldest
                                            </DropdownMenuRadioItem>
                                            <DropdownMenuRadioItem value="priority">
                                                Priority
                                            </DropdownMenuRadioItem>
                                            <DropdownMenuRadioItem value="due_soonest">
                                                Due Soonest
                                            </DropdownMenuRadioItem>
                                        </DropdownMenuRadioGroup>
                                    </DropdownMenuContent>
                                </DropdownMenu>

                                <Button
                                    variant="default"
                                    size="sm"
                                    onClick={openCreateSheet}
                                    className="h-9 flex-1 rounded-lg font-semibold sm:flex-none"
                                >
                                    <CheckSquare className="mr-2 h-4 w-4" />
                                    New Task
                                    <kbd className="ml-2 hidden rounded border border-primary-foreground/25 px-1.5 font-mono text-[10px] font-medium text-primary-foreground/75 select-none sm:inline-block">
                                        N
                                    </kbd>
                                </Button>
                            </div>
                        </div>
                    </div>

                    <div className="overflow-hidden rounded-xl border bg-background">
                        <MyTasksTable
                            tasks={tasks}
                            onViewTask={setViewingTaskId}
                            hasActiveFilters={hasActiveFilters}
                            onClearFilters={clearFilters}
                            onCreateTask={openCreateSheet}
                            startNumber={pagination.from ?? 1}
                        />
                    </div>

                    <DataPagination
                        pagination={pagination}
                        only={['tasks', 'pagination', 'summary']}
                    />
                </section>
            </div>

            <MyTaskDetailSheet
                task={viewingTask}
                parentStatus={parentStatusOf(viewingTask)}
                open={!!viewingTaskId}
                onOpenChange={(open) => !open && setViewingTaskId(null)}
                onEdit={(task) => {
                    setViewingTaskId(null);
                    setEditingTask(task);
                }}
                onDelete={(task) => {
                    setViewingTaskId(null);
                    setDeletingTask(task);
                }}
                onNavigate={(id) => setViewingTaskId(id)}
            />

            <MyTaskFormSheet
                open={isCreateSheetOpen}
                onOpenChange={setIsCreateSheetOpen}
                parentId={subtaskParentId}
            />

            <MyTaskFormSheet
                open={editingTask !== null}
                onOpenChange={(open) => !open && setEditingTask(null)}
                task={editingTask}
                parentStatus={parentStatusOf(editingTask)}
            />

            <ConfirmDeleteDialog
                open={deletingTask !== null}
                onOpenChange={(open) => !open && setDeletingTask(null)}
                onConfirm={handleDelete}
                processing={processingDelete}
                variant="center"
                icon={AlertCircle}
                title="Delete task?"
                description={
                    <>
                        Delete{' '}
                        <span className="font-bold text-foreground">
                            "{deletingTask?.title}"
                        </span>
                        ? Its subtasks will be deleted too and this cannot be
                        undone.
                    </>
                }
                confirmLabel="Delete"
                cancelLabel="Cancel"
                processingLabel="Deleting..."
            />
        </>
    );
}
