import { Head, Link, router } from '@inertiajs/react';
import { Columns3, List } from 'lucide-react';
import { useEffect, useMemo, useState } from 'react';
import KanbanController from '@/actions/App/Http/Controllers/Admin/KanbanController';
import {
    KanbanBoard,
    type KanbanCard,
    type KanbanColumn,
} from '@/components/kanban-board';
import { KanbanCreateDialog } from '@/components/kanban-create-dialog';
import {
    KanbanItemSheet,
    type KanbanSheetItem,
} from '@/components/kanban-item-sheet';
import Heading from '@/components/heading';
import { Button } from '@/components/ui/button';
import {
    Select,
    SelectContent,
    SelectItem,
    SelectTrigger,
    SelectValue,
} from '@/components/ui/select';
import {
    ToggleGroup,
    ToggleGroupItem,
} from '@/components/ui/toggle-group';
import { dashboard } from '@/routes';
import { index as projectsIndex, kanban } from '@/routes/admin/projects';
import { index as tasksIndex } from '@/routes/admin/tasks';
import { index as ticketsIndex } from '@/routes/admin/tickets';

type ProjectOption = {
    id: number;
    code: string;
    name: string;
};

type UserOption = {
    id: number;
    name: string;
};

type StatusOption = {
    value: string;
    label: string;
};

type TaskItem = KanbanCard & {
    status: string;
    priority: string;
    assigned_to: number | null;
    project_id: number;
};

type TicketItem = KanbanCard & {
    status: string;
    priority: string;
    assigned_to: number | null;
    project_id: number;
    category: string;
};

type Filters = {
    project_id: number | null;
    assigned_to: number | null;
    board: 'tasks' | 'tickets';
};

type Truncated = {
    tasks: boolean;
    tickets: boolean;
};

function visitKanban(params: {
    project_id: number | null;
    assigned_to: number | null;
    board: 'tasks' | 'tickets';
}) {
    router.get(
        kanban.url(),
        {
            project_id: params.project_id ?? undefined,
            assigned_to: params.assigned_to ?? undefined,
            board: params.board,
        },
        {
            preserveState: true,
            replace: true,
            preserveScroll: true,
        },
    );
}

export default function ProjectsKanban({
    tasks,
    tickets,
    filters,
    truncated,
    projects,
    users,
    taskStatuses,
    ticketStatuses,
    taskPriorities,
    ticketPriorities,
    ticketCategories,
    canUpdateTasks,
    canUpdateTickets,
    canCreateTasks,
    canCreateTickets,
    canViewTasks,
    canViewTickets,
}: {
    tasks: TaskItem[];
    tickets: TicketItem[];
    filters: Filters;
    truncated: Truncated;
    projects: ProjectOption[];
    users: UserOption[];
    taskStatuses: StatusOption[];
    ticketStatuses: StatusOption[];
    taskPriorities: StatusOption[];
    ticketPriorities: StatusOption[];
    ticketCategories: StatusOption[];
    canUpdateTasks: boolean;
    canUpdateTickets: boolean;
    canCreateTasks: boolean;
    canCreateTickets: boolean;
    canViewTasks: boolean;
    canViewTickets: boolean;
}) {
    const defaultBoard = canViewTasks
        ? 'tasks'
        : canViewTickets
          ? 'tickets'
          : 'tasks';

    const [board, setBoard] = useState<'tasks' | 'tickets'>(
        filters.board === 'tickets' && canViewTickets ? 'tickets' : defaultBoard,
    );
    const [projectFilter, setProjectFilter] = useState(
        filters.project_id ? String(filters.project_id) : 'all',
    );
    const [assigneeFilter, setAssigneeFilter] = useState(
        filters.assigned_to ? String(filters.assigned_to) : 'all',
    );
    const [localTasks, setLocalTasks] = useState(tasks);
    const [localTickets, setLocalTickets] = useState(tickets);
    const [sheetItem, setSheetItem] = useState<KanbanSheetItem | null>(null);
    const [sheetOpen, setSheetOpen] = useState(false);
    const [createOpen, setCreateOpen] = useState(false);
    const [createColumn, setCreateColumn] = useState<KanbanColumn | null>(null);

    useEffect(() => {
        setLocalTasks(tasks);
    }, [tasks]);

    useEffect(() => {
        setLocalTickets(tickets);
    }, [tickets]);

    useEffect(() => {
        setProjectFilter(
            filters.project_id ? String(filters.project_id) : 'all',
        );
        setAssigneeFilter(
            filters.assigned_to ? String(filters.assigned_to) : 'all',
        );
        setBoard(
            filters.board === 'tickets' && canViewTickets
                ? 'tickets'
                : defaultBoard,
        );
    }, [filters, canViewTickets, defaultBoard]);

    const columns: KanbanColumn[] = useMemo(
        () => (board === 'tasks' ? taskStatuses : ticketStatuses),
        [board, taskStatuses, ticketStatuses],
    );

    const items = board === 'tasks' ? localTasks : localTickets;
    const canDrag = board === 'tasks' ? canUpdateTasks : canUpdateTickets;
    const canCreate = board === 'tasks' ? canCreateTasks : canCreateTickets;
    const canUpdateSheet =
        board === 'tasks' ? canUpdateTasks : canUpdateTickets;

    function currentFilters(overrides?: {
        project_id?: number | null;
        assigned_to?: number | null;
        board?: 'tasks' | 'tickets';
    }) {
        return {
            project_id:
                overrides?.project_id !== undefined
                    ? overrides.project_id
                    : projectFilter === 'all'
                      ? null
                      : Number(projectFilter),
            assigned_to:
                overrides?.assigned_to !== undefined
                    ? overrides.assigned_to
                    : assigneeFilter === 'all'
                      ? null
                      : Number(assigneeFilter),
            board: overrides?.board ?? board,
        };
    }

    function handleMove(itemId: number, status: string) {
        if (board === 'tasks') {
            const previous = localTasks;
            setLocalTasks((current) =>
                current.map((item) =>
                    item.id === itemId ? { ...item, status } : item,
                ),
            );

            router.patch(
                KanbanController.updateTaskStatus.url(itemId),
                { status },
                {
                    preserveScroll: true,
                    preserveState: true,
                    onError: () => setLocalTasks(previous),
                },
            );

            return;
        }

        const previous = localTickets;
        setLocalTickets((current) =>
            current.map((item) =>
                item.id === itemId ? { ...item, status } : item,
            ),
        );

        router.patch(
            KanbanController.updateTicketStatus.url(itemId),
            { status },
            {
                preserveScroll: true,
                preserveState: true,
                onError: () => setLocalTickets(previous),
            },
        );
    }

    function handleCardClick(card: KanbanCard) {
        if (board === 'tasks') {
            const task = localTasks.find((item) => item.id === card.id);
            if (!task) {
                return;
            }

            setSheetItem({
                id: task.id,
                code: task.code,
                title: task.title,
                type: 'task',
                status: task.status,
                priority: task.priority,
                assigned_to: task.assigned_to,
                due_date: task.due_date ?? null,
                completion_percent: task.completion_percent,
            });
            setSheetOpen(true);

            return;
        }

        const ticket = localTickets.find((item) => item.id === card.id);
        if (!ticket) {
            return;
        }

        setSheetItem({
            id: ticket.id,
            code: ticket.code,
            title: ticket.title,
            type: 'ticket',
            status: ticket.status,
            priority: ticket.priority,
            assigned_to: ticket.assigned_to,
            due_date: ticket.due_date ?? null,
            category: ticket.category,
        });
        setSheetOpen(true);
    }

    function handleAddColumn(column: KanbanColumn) {
        setCreateColumn(column);
        setCreateOpen(true);
    }

    return (
        <>
            <Head title="Kanban projets" />

            <div className="flex h-full flex-1 flex-col gap-6 p-4 md:p-6">
                <div className="flex flex-col gap-4 lg:flex-row lg:items-start lg:justify-between">
                    <Heading
                        title="Kanban"
                        description="Suivi et planification légère des tâches et tickets"
                    />

                    <div className="flex flex-wrap items-center gap-2">
                        {canViewTasks && (
                            <Button variant="outline" asChild>
                                <Link href={tasksIndex.url()}>
                                    <List />
                                    Liste tâches
                                </Link>
                            </Button>
                        )}
                        {canViewTickets && (
                            <Button variant="outline" asChild>
                                <Link href={ticketsIndex.url()}>
                                    <List />
                                    Liste tickets
                                </Link>
                            </Button>
                        )}
                    </div>
                </div>

                <div className="flex flex-col gap-4 lg:flex-row lg:items-center lg:justify-between">
                    {canViewTasks && canViewTickets ? (
                        <ToggleGroup
                            type="single"
                            variant="outline"
                            value={board}
                            onValueChange={(value) => {
                                if (value !== 'tasks' && value !== 'tickets') {
                                    return;
                                }

                                setBoard(value);
                                visitKanban(currentFilters({ board: value }));
                            }}
                        >
                            <ToggleGroupItem value="tasks">
                                Tâches
                            </ToggleGroupItem>
                            <ToggleGroupItem value="tickets">
                                Tickets
                            </ToggleGroupItem>
                        </ToggleGroup>
                    ) : (
                        <div className="flex items-center gap-2 text-sm font-medium">
                            <Columns3 className="size-4" />
                            {board === 'tasks' ? 'Tâches' : 'Tickets'}
                        </div>
                    )}

                    <div className="flex flex-wrap gap-2">
                        <Select
                            value={projectFilter}
                            onValueChange={(value) => {
                                setProjectFilter(value);
                                visitKanban(
                                    currentFilters({
                                        project_id:
                                            value === 'all'
                                                ? null
                                                : Number(value),
                                    }),
                                );
                            }}
                        >
                            <SelectTrigger className="w-56">
                                <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={assigneeFilter}
                            onValueChange={(value) => {
                                setAssigneeFilter(value);
                                visitKanban(
                                    currentFilters({
                                        assigned_to:
                                            value === 'all'
                                                ? null
                                                : Number(value),
                                    }),
                                );
                            }}
                        >
                            <SelectTrigger className="w-48">
                                <SelectValue placeholder="Assigné" />
                            </SelectTrigger>
                            <SelectContent>
                                <SelectItem value="all">
                                    Tous les assignés
                                </SelectItem>
                                {users.map((user) => (
                                    <SelectItem
                                        key={user.id}
                                        value={String(user.id)}
                                    >
                                        {user.name}
                                    </SelectItem>
                                ))}
                            </SelectContent>
                        </Select>
                    </div>
                </div>

                {!canDrag && (
                    <p className="text-muted-foreground text-sm">
                        Vous pouvez consulter le tableau, mais vous n’avez pas
                        la permission de déplacer les cartes.
                    </p>
                )}

                {(board === 'tasks' ? truncated.tasks : truncated.tickets) && (
                    <p className="text-sm text-amber-600 dark:text-amber-500">
                        Trop d’éléments à afficher : seuls les plus récents
                        sont chargés. Filtrez par projet ou par assigné pour
                        voir le reste.
                    </p>
                )}

                <KanbanBoard
                    columns={columns}
                    items={items}
                    canDrag={canDrag}
                    canCreate={canCreate}
                    onMove={handleMove}
                    onCardClick={handleCardClick}
                    onAddColumn={handleAddColumn}
                />
            </div>

            <KanbanItemSheet
                open={sheetOpen}
                onOpenChange={setSheetOpen}
                item={sheetItem}
                users={users}
                priorities={
                    board === 'tasks' ? taskPriorities : ticketPriorities
                }
                categories={ticketCategories}
                canUpdate={canUpdateSheet}
            />

            {createColumn && (
                <KanbanCreateDialog
                    open={createOpen}
                    onOpenChange={setCreateOpen}
                    type={board === 'tasks' ? 'task' : 'ticket'}
                    status={createColumn.value}
                    statusLabel={createColumn.label}
                    projectId={
                        projectFilter === 'all'
                            ? null
                            : Number(projectFilter)
                    }
                    projects={projects}
                />
            )}
        </>
    );
}

ProjectsKanban.layout = {
    breadcrumbs: [
        { title: 'Tableau de bord', href: dashboard() },
        { title: 'Gestion de projets', href: projectsIndex() },
        { title: 'Kanban', href: kanban() },
    ],
};
