import { Head, Link, router } from '@inertiajs/react';
import { createColumnHelper } from '@tanstack/react-table';
import type { ColumnDef, PaginationState, SortingState } from '@tanstack/react-table';
import { Pencil, Plus, Trash2, Columns3 } from 'lucide-react';
import { useEffect, useMemo, useRef, useState } from 'react';
import TaskController from '@/actions/App/Http/Controllers/Admin/TaskController';
import { ConfirmDialog } from '@/components/confirm-dialog';
import {
    DataTable,
    DataTableBulkDelete,
    DataTableColumnHeader,
    withSelectionColumn,
} from '@/components/data-table';
import Heading from '@/components/heading';
import { Button } from '@/components/ui/button';
import {
    Select,
    SelectContent,
    SelectItem,
    SelectTrigger,
    SelectValue,
} from '@/components/ui/select';
import { useCan, useHasRole } from '@/hooks/use-can';
import { cn, formatDate } from '@/lib/utils';
import { dashboard } from '@/routes';
import { index as projectsIndex, kanban, show as projectShow } from '@/routes/admin/projects';
import { index, show } from '@/routes/admin/tasks';
import type { Paginated, TableFilters } from '@/types';
import { TaskPriorityBadge } from './priority-badge';
import { TaskStatusBadge } from './status-badge';
import {
    TaskFormModal,
    type EnumOption,
    type ProjectOption,
    type TaskFormValues,
    type TicketOption,
    type UserOption,
} from './task-form-modal';

type AdminTask = TaskFormValues & {
    code: string;
    status_label: string;
    priority_label: string;
    project: { id: number; code: string; name: string } | null;
    ticket: { id: number; code: string; title: string } | null;
    assignee: { id: number; name: string } | null;
    creator: { id: number; name: string } | null;
    created_at: string | null;
};

type TaskFilters = TableFilters & {
    project_id: number | null;
    ticket_id: number | null;
    status: string | null;
    priority: string | null;
};

const columnHelper = createColumnHelper<AdminTask>();

function visitTasks(params: {
    search: string;
    sort: string;
    direction: 'asc' | 'desc';
    page: number;
    per_page: number;
    project_id: number | null;
    status: string | null;
    priority: string | null;
}) {
    router.get(
        index.url(),
        {
            search: params.search || undefined,
            sort: params.sort,
            direction: params.direction,
            page: params.page > 1 ? params.page : undefined,
            per_page: params.per_page !== 15 ? params.per_page : undefined,
            project_id: params.project_id ?? undefined,
            status: params.status ?? undefined,
            priority: params.priority ?? undefined,
        },
        {
            preserveState: true,
            replace: true,
            preserveScroll: true,
        },
    );
}

export default function TasksIndex({
    tasks,
    filters,
    projects,
    tickets,
    users,
    statuses,
    priorities,
}: {
    tasks: Paginated<AdminTask>;
    filters: TaskFilters;
    projects: ProjectOption[];
    tickets: TicketOption[];
    users: UserOption[];
    statuses: EnumOption[];
    priorities: EnumOption[];
}) {
    const canCreate = useCan('tasks.create');
    const canUpdate = useCan('tasks.update');
    const canDelete = useCan('tasks.delete') || useHasRole('super-admin');
    const isFirstSearchEffect = useRef(true);
    const [isLoading, setIsLoading] = useState(false);
    const [modalOpen, setModalOpen] = useState(false);
    const [editingTask, setEditingTask] = useState<AdminTask | null>(null);

    const [search, setSearch] = useState(filters.search);
    const [projectFilter, setProjectFilter] = useState(
        filters.project_id ? String(filters.project_id) : 'all',
    );
    const [statusFilter, setStatusFilter] = useState(filters.status ?? 'all');
    const [priorityFilter, setPriorityFilter] = useState(
        filters.priority ?? 'all',
    );
    const [sorting, setSorting] = useState<SortingState>([
        {
            id: filters.sort,
            desc: filters.direction === 'desc',
        },
    ]);
    const [pagination, setPagination] = useState<PaginationState>({
        pageIndex: tasks.current_page - 1,
        pageSize: tasks.per_page,
    });

    useEffect(() => {
        const removeStart = router.on('start', () => setIsLoading(true));
        const removeFinish = router.on('finish', () => setIsLoading(false));

        return () => {
            removeStart();
            removeFinish();
        };
    }, []);

    useEffect(() => {
        setSearch(filters.search);
        setProjectFilter(
            filters.project_id ? String(filters.project_id) : 'all',
        );
        setStatusFilter(filters.status ?? 'all');
        setPriorityFilter(filters.priority ?? 'all');
        setSorting([
            {
                id: filters.sort,
                desc: filters.direction === 'desc',
            },
        ]);
        setPagination({
            pageIndex: tasks.current_page - 1,
            pageSize: tasks.per_page,
        });
    }, [filters, tasks.current_page, tasks.per_page]);

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

            return;
        }

        const timeout = window.setTimeout(() => {
            const sort = sorting[0];

            visitTasks({
                search,
                sort: sort?.id ?? 'created_at',
                direction: sort?.desc === false ? 'asc' : 'desc',
                page: 1,
                per_page: pagination.pageSize,
                project_id:
                    projectFilter === 'all' ? null : Number(projectFilter),
                status: statusFilter === 'all' ? null : statusFilter,
                priority: priorityFilter === 'all' ? null : priorityFilter,
            });
        }, 300);

        return () => window.clearTimeout(timeout);
        // eslint-disable-next-line react-hooks/exhaustive-deps
    }, [search]);

    function applyFilters(next: {
        project_id?: string;
        status?: string;
        priority?: string;
    }) {
        const project = next.project_id ?? projectFilter;
        const status = next.status ?? statusFilter;
        const priority = next.priority ?? priorityFilter;
        const sort = sorting[0];

        visitTasks({
            search,
            sort: sort?.id ?? 'created_at',
            direction: sort?.desc === false ? 'asc' : 'desc',
            page: 1,
            per_page: pagination.pageSize,
            project_id: project === 'all' ? null : Number(project),
            status: status === 'all' ? null : status,
            priority: priority === 'all' ? null : priority,
        });
    }

    function openCreateModal() {
        setEditingTask(null);
        setModalOpen(true);
    }

    function openEditModal(task: AdminTask) {
        setEditingTask(task);
        setModalOpen(true);
    }

    const columns = useMemo(
        () =>
            withSelectionColumn([
                columnHelper.accessor('code', {
                    header: ({ column }) => (
                        <DataTableColumnHeader column={column} title="Code" />
                    ),
                    meta: { label: 'Code' },
                    cell: (info) => (
                        <span className="font-mono text-sm">
                            {info.getValue()}
                        </span>
                    ),
                }),
                columnHelper.accessor('title', {
                    header: ({ column }) => (
                        <DataTableColumnHeader column={column} title="Titre" />
                    ),
                    meta: { label: 'Titre' },
                    cell: (info) => (
                        <Link
                            href={show(info.row.original.id)}
                            className="font-medium hover:underline"
                        >
                            {info.getValue()}
                        </Link>
                    ),
                }),
                columnHelper.accessor('project', {
                    header: 'Projet',
                    enableSorting: false,
                    meta: { label: 'Projet' },
                    cell: (info) => {
                        const project = info.getValue();

                        if (!project) {
                            return '—';
                        }

                        return (
                            <Link
                                href={projectShow(project.id)}
                                className="text-muted-foreground hover:underline"
                            >
                                {project.code} — {project.name}
                            </Link>
                        );
                    },
                }),
                columnHelper.accessor('ticket', {
                    header: 'Ticket',
                    enableSorting: false,
                    meta: { label: 'Ticket' },
                    cell: (info) => {
                        const ticket = info.getValue();

                        return (
                            <span className="text-muted-foreground font-mono text-sm">
                                {ticket?.code ?? '—'}
                            </span>
                        );
                    },
                }),
                columnHelper.accessor('status', {
                    header: ({ column }) => (
                        <DataTableColumnHeader column={column} title="Statut" />
                    ),
                    meta: { label: 'Statut' },
                    cell: (info) => (
                        <TaskStatusBadge
                            status={info.getValue()}
                            label={info.row.original.status_label}
                        />
                    ),
                }),
                columnHelper.accessor('priority', {
                    header: ({ column }) => (
                        <DataTableColumnHeader
                            column={column}
                            title="Priorité"
                        />
                    ),
                    meta: { label: 'Priorité' },
                    cell: (info) => (
                        <TaskPriorityBadge
                            priority={info.getValue()}
                            label={info.row.original.priority_label}
                        />
                    ),
                }),
                columnHelper.accessor('completion_percent', {
                    header: ({ column }) => (
                        <DataTableColumnHeader
                            column={column}
                            title="Complétion"
                        />
                    ),
                    meta: { label: 'Complétion' },
                    cell: (info) => {
                        const value = info.getValue();

                        return (
                            <div className="flex min-w-28 items-center gap-2">
                                <div className="bg-muted h-2 flex-1 overflow-hidden rounded-full">
                                    <div
                                        className={cn('bg-primary h-full')}
                                        style={{ width: `${value}%` }}
                                    />
                                </div>
                                <span className="text-muted-foreground w-10 text-right text-xs tabular-nums">
                                    {value} %
                                </span>
                            </div>
                        );
                    },
                }),
                columnHelper.accessor('assignee', {
                    header: 'Assigné à',
                    enableSorting: false,
                    meta: { label: 'Assigné à' },
                    cell: (info) => (
                        <span className="text-muted-foreground">
                            {info.getValue()?.name ?? '—'}
                        </span>
                    ),
                }),
                columnHelper.accessor('due_date', {
                    header: ({ column }) => (
                        <DataTableColumnHeader
                            column={column}
                            title="Échéance"
                        />
                    ),
                    meta: { label: 'Échéance' },
                    cell: (info) => (
                        <span className="text-muted-foreground">
                            {info.getValue()
                                ? formatDate(info.getValue())
                                : '—'}
                        </span>
                    ),
                }),
                columnHelper.display({
                    id: 'actions',
                    enableSorting: false,
                    enableHiding: false,
                    header: () => <div className="text-right">Actions</div>,
                    cell: ({ row }) => {
                        const task = row.original;

                        return (
                            <div className="flex justify-end gap-1">
                                {canUpdate && (
                                    <Button
                                        variant="outline"
                                        size="icon"
                                        aria-label={`Modifier ${task.title}`}
                                        onClick={() => openEditModal(task)}
                                    >
                                        <Pencil />
                                    </Button>
                                )}
                                {canDelete && (
                                    <ConfirmDialog
                                        trigger={
                                            <Button
                                                variant="destructive"
                                                size="icon"
                                                aria-label={`Supprimer ${task.title}`}
                                            >
                                                <Trash2 />
                                            </Button>
                                        }
                                        title={`Supprimer la tâche ${task.code} ?`}
                                        description="Cette action est irréversible."
                                        confirmLabel="Supprimer"
                                        onConfirm={() => {
                                            router.delete(
                                                TaskController.destroy.url(
                                                    task.id,
                                                ),
                                                { preserveScroll: true },
                                            );
                                        }}
                                    />
                                )}
                            </div>
                        );
                    },
                }),
            ] as ColumnDef<AdminTask>[]),
        [canUpdate, canDelete],
    );

    return (
        <>
            <Head title="Exécution des tâches" />

            <div className="flex h-full flex-1 flex-col gap-6 p-4 md:p-6">
                <div className="flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between">
                    <Heading
                        title="Exécution des tâches"
                        description="Suivi et exécution des tâches de projet"
                    />
                    <div className="flex flex-wrap gap-2">
                        <Button variant="outline" asChild>
                            <Link
                                href={kanban.url({
                                    query: {
                                        board: 'tasks',
                                        project_id:
                                            projectFilter === 'all'
                                                ? undefined
                                                : Number(projectFilter),
                                    },
                                })}
                            >
                                <Columns3 />
                                Kanban
                            </Link>
                        </Button>
                        {canCreate && (
                            <Button onClick={openCreateModal}>
                                <Plus />
                                Nouvelle tâche
                            </Button>
                        )}
                    </div>
                </div>

                <div className="flex flex-wrap gap-3">
                    <Select
                        value={projectFilter}
                        onValueChange={(value) => {
                            setProjectFilter(value);
                            applyFilters({ project_id: value });
                        }}
                    >
                        <SelectTrigger className="w-55">
                            <SelectValue placeholder="Projet" />
                        </SelectTrigger>
                        <SelectContent>
                            <SelectItem value="all">Tous les projets</SelectItem>
                            {projects.map((project) => (
                                <SelectItem
                                    key={project.id}
                                    value={String(project.id)}
                                >
                                    {project.code} — {project.name}
                                </SelectItem>
                            ))}
                        </SelectContent>
                    </Select>

                    <Select
                        value={statusFilter}
                        onValueChange={(value) => {
                            setStatusFilter(value);
                            applyFilters({ status: value });
                        }}
                    >
                        <SelectTrigger className="w-45">
                            <SelectValue placeholder="Statut" />
                        </SelectTrigger>
                        <SelectContent>
                            <SelectItem value="all">Tous les statuts</SelectItem>
                            {statuses.map((status) => (
                                <SelectItem
                                    key={status.value}
                                    value={status.value}
                                >
                                    {status.label}
                                </SelectItem>
                            ))}
                        </SelectContent>
                    </Select>

                    <Select
                        value={priorityFilter}
                        onValueChange={(value) => {
                            setPriorityFilter(value);
                            applyFilters({ priority: value });
                        }}
                    >
                        <SelectTrigger className="w-45">
                            <SelectValue placeholder="Priorité" />
                        </SelectTrigger>
                        <SelectContent>
                            <SelectItem value="all">
                                Toutes les priorités
                            </SelectItem>
                            {priorities.map((priority) => (
                                <SelectItem
                                    key={priority.value}
                                    value={priority.value}
                                >
                                    {priority.label}
                                </SelectItem>
                            ))}
                        </SelectContent>
                    </Select>
                </div>

                <DataTable
                    id="admin-tasks"
                    columns={columns}
                    data={tasks.data}
                    getRowId={(row) => String(row.id)}
                    isLoading={isLoading}
                    searchValue={search}
                    onSearchChange={setSearch}
                    searchPlaceholder="Rechercher par code, titre, projet, assigné…"
                    emptyMessage="Aucune tâche."
                    sorting={sorting}
                    onSortingChange={(updater) => {
                        const next =
                            typeof updater === 'function'
                                ? updater(sorting)
                                : updater;
                        setSorting(next);

                        const sort = next[0];
                        visitTasks({
                            search,
                            sort: sort?.id ?? 'created_at',
                            direction: sort?.desc === false ? 'asc' : 'desc',
                            page: 1,
                            per_page: pagination.pageSize,
                            project_id:
                                projectFilter === 'all'
                                    ? null
                                    : Number(projectFilter),
                            status:
                                statusFilter === 'all' ? null : statusFilter,
                            priority:
                                priorityFilter === 'all'
                                    ? null
                                    : priorityFilter,
                        });
                    }}
                    manualSorting
                    pagination={pagination}
                    onPaginationChange={(updater) => {
                        const next =
                            typeof updater === 'function'
                                ? updater(pagination)
                                : updater;
                        setPagination(next);

                        const sort = sorting[0];
                        visitTasks({
                            search,
                            sort: sort?.id ?? 'created_at',
                            direction: sort?.desc === false ? 'asc' : 'desc',
                            page: next.pageIndex + 1,
                            per_page: next.pageSize,
                            project_id:
                                projectFilter === 'all'
                                    ? null
                                    : Number(projectFilter),
                            status:
                                statusFilter === 'all' ? null : statusFilter,
                            priority:
                                priorityFilter === 'all'
                                    ? null
                                    : priorityFilter,
                        });
                    }}
                    manualPagination
                    pageCount={tasks.last_page}
                    rowCount={tasks.total}
                    toolbarActions={
                        canDelete ? (
                            <DataTableBulkDelete
                                onConfirm={(ids) => {
                                    router.delete(
                                        TaskController.bulkDestroy.url(),
                                        {
                                            data: { ids },
                                            preserveScroll: true,
                                        },
                                    );
                                }}
                            />
                        ) : undefined
                    }
                />
            </div>

            <TaskFormModal
                open={modalOpen}
                onOpenChange={setModalOpen}
                task={editingTask}
                projects={projects}
                tickets={tickets}
                users={users}
                statuses={statuses}
                priorities={priorities}
            />
        </>
    );
}

TasksIndex.layout = {
    breadcrumbs: [
        { title: 'Tableau de bord', href: dashboard() },
        { title: 'Gestion de projets', href: projectsIndex() },
        { title: 'Tâches', href: index() },
    ],
};
