import {
    Head,
    router,
    setLayoutProps,
    usePage,
    usePoll,
} from '@inertiajs/react';
import {
    CalendarClock,
    CheckCircle2,
    FolderKanban,
    Info,
    Settings,
    Users,
} from 'lucide-react';
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { toast } from 'sonner';

import { updateStatus as projectUpdateStatus } from '@/actions/App/Domains/Project/Http/Controllers/ProjectController';
import { AddMemberDialog } from '@/components/projects/AddMemberDialog';
import { DeleteProjectDialog } from '@/components/projects/DeleteProjectDialog';
import { DuplicateProjectDialog } from '@/components/projects/DuplicateProjectDialog';
import { EditMemberRoleDialog } from '@/components/projects/EditMemberRoleDialog';
import { EditProjectDialog } from '@/components/projects/EditProjectDialog';
import { ProjectGantt } from '@/components/projects/ProjectGantt';
import { ProjectInfo } from '@/components/projects/ProjectInfo';
import { ProjectSettings } from '@/components/projects/ProjectSettings';
import { ProjectTeam } from '@/components/projects/ProjectTeam';
import { RemoveMemberDialog } from '@/components/projects/RemoveMemberDialog';
import { TaskList } from '@/components/TaskList';
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';
import { useTaskDeepLink } from '@/hooks/use-task-deep-link';
import { PROJECT_STATUS_MAP } from '@/lib/status-config';
import { mapApiTasksToTaskoTasks } from '@/lib/task-mappers';
import { index as projectsIndex, show as projectShow } from '@/routes/projects';
import type { Auth } from '@/types';
import type {
    PaginatedData,
    ProjectActivity,
    ProjectGanttData,
    ProjectPermissions,
    ProjectShowData,
    ProjectTask,
    ProjectTaskSummary,
    ProjectTeamMember,
} from '@/types/project';
import type { Status } from '@/types/task';

interface ProjectShowProps {
    project: ProjectShowData | null;
    tasks: PaginatedData<ProjectTask>;
    taskSummary: ProjectTaskSummary;
    activities: PaginatedData<ProjectActivity>;
    /** Prop opsional: baru dikirim server saat tab Gantt memintanya. */
    gantt?: ProjectGanttData;
    activeTab?: string;
    can: ProjectPermissions;
}

interface ProjectShowContentProps extends Omit<ProjectShowProps, 'project'> {
    project: ProjectShowData;
}

export default function ProjectsShow(props: ProjectShowProps) {
    if (!props.project) {
        return (
            <div className="flex h-screen items-center justify-center text-muted-foreground">
                Project data not found or still loading...
            </div>
        );
    }

    return <ProjectShowContent {...props} project={props.project} />;
}

function ProjectShowContent({
    project,
    tasks,
    taskSummary,
    activities,
    gantt,
    activeTab: serverTab = 'tasks',
    can = {
        update: false,
        delete: false,
        manageMembers: false,
        duplicate: false,
        manageTasks: false,
    },
}: ProjectShowContentProps) {
    const [isEditOpen, setIsEditOpen] = useState(false);
    const [isDuplicateOpen, setIsDuplicateOpen] = useState(false);
    const [isDeleteOpen, setIsDeleteOpen] = useState(false);
    const [isAddMemberOpen, setIsAddMemberOpen] = useState(false);
    const [isEditRoleOpen, setIsEditRoleOpen] = useState(false);
    const [isRemoveMemberOpen, setIsRemoveMemberOpen] = useState(false);
    const [selectedMember, setSelectedMember] =
        useState<ProjectTeamMember | null>(null);
    const { auth } = usePage<Auth>().props;
    const currentUserId = String(auth.user.id);

    // Auto-refresh data project (task, member, status, activity log) tanpa
    // refresh manual.
    // - State komponen dipertahankan oleh Inertia (sheet/dialog yang sedang
    //   terbuka tidak ikut tertutup).
    // - `activities` ikut di-reload agar timeline tidak beku saat metrik task
    //   bergerak. Paginasinya berbasis offset, jadi di halaman >1 isinya bisa
    //   bergeser saat ada aktivitas baru; dianggap wajar karena mayoritas user
    //   berhenti di halaman 1.
    // - `keepAlive: false` (default): polling berhenti saat tab tidak aktif.
    // - Polling di-pause saat ada dialog level-halaman terbuka agar reload tidak
    //   menimpa data yang sedang diedit user.
    // Sheet task dilaporkan keluar oleh TaskList; tanpa itu polling tetap
    // berjalan justru saat user membuka atau mengedit task, yang persis
    // keadaan yang ingin dihindari komentar di atas.
    const [isTaskSheetOpen, setIsTaskSheetOpen] = useState(false);

    const isAnyDialogOpen =
        isEditOpen ||
        isDuplicateOpen ||
        isDeleteOpen ||
        isAddMemberOpen ||
        isEditRoleOpen ||
        isRemoveMemberOpen ||
        isTaskSheetOpen;

    const { start, stop } = usePoll(
        10000,
        { only: ['tasks', 'taskSummary', 'project', 'activities'] },
        { autoStart: false },
    );

    useEffect(() => {
        if (isAnyDialogOpen) {
            stop();

            return;
        }

        start();
    }, [isAnyDialogOpen, start, stop]);

    const currentStatus = (project.status || 'draft').toLowerCase();

    // Flag guard dihitung di server (taskSummary) dari seluruh task project.
    const hasIncompleteTasks = taskSummary.has_incomplete;
    const hasStartedTasks = taskSummary.has_started;

    const handleUpdateStatus = (statusVal: string) => {
        const normalizedTarget = statusVal.toLowerCase();

        // Guard preemptive: cegah pindah ke Completed bila masih ada task aktif.
        // Validasi final (dengan rincian jumlah) tetap ditegakkan di backend.
        if (normalizedTarget === 'completed' && hasIncompleteTasks) {
            toast.error('Cannot change to Completed', {
                description:
                    'Some tasks are still unfinished. Complete all of them first!',
                duration: 6000,
            });

            return;
        }

        router.patch(
            projectUpdateStatus({ project: project.id }).url,
            {
                status: statusVal,
            },
            {
                preserveScroll: true,
            },
        );
    };

    // Initialize state directly from server-side query prop (eliminates initial blink/flash)
    const [activeTab, setActiveTab] = useState(serverTab);

    const handleTabChange = (val: string) => {
        setActiveTab(val);

        const url = new URL(window.location.href);
        url.searchParams.set('tab', val);
        // `window.history.state` diteruskan apa adanya, bukan ditimpa `{}`,
        // supaya snapshot halaman milik Inertia (`state.page`) tetap utuh —
        // tanpa itu restorasi scroll berhenti dan `decrypt()` melempar.
        window.history.replaceState(window.history.state, '', url.toString());
    };

    // Prop `gantt` opsional di server (Inertia::optional), jadi tab-nya yang
    // meminta sendiri saat pertama dibuka: berpindah tab hanya menulis ulang URL
    // dan tidak pernah menembak request.
    //
    // Penjaganya ref, bukan sekadar `!gantt`: di StrictMode efek ini berjalan
    // dua kali sebelum prop-nya sempat terisi, sehingga tanpa ref keduanya
    // sama-sama mengirim request.
    const ganttRequested = useRef(false);

    useEffect(() => {
        // Prop yang sudah tiba melepas penjaganya kembali. Prop opsional TIDAK
        // ikut terkirim pada kunjungan penuh (mis. filter atau paginasi task),
        // jadi tanpa pelepasan ini bagan hanya bisa dimuat sekali seumur
        // halaman: sesudahnya `gantt` hilang, penjaganya masih menyala, dan tab
        // Gantt tinggal kerangka yang tidak pernah terisi lagi.
        if (gantt) {
            ganttRequested.current = false;

            return;
        }

        if (activeTab !== 'gantt' || ganttRequested.current) {
            return;
        }

        ganttRequested.current = true;
        router.reload({ only: ['gantt'] });
    }, [activeTab, gantt]);

    setLayoutProps({
        breadcrumbs: [
            {
                title: 'Projects',
                href: projectsIndex().url,
            },
            {
                title: project.name,
            },
        ],
    });

    // Map backend data to what the components expect
    const projectShowUrl = projectShow({ project: project.id }).url;

    // Konteks project untuk mapper API → Task frontend. Dipakai baik oleh
    // daftar task (tab Tasks) maupun detail task yang dibuka dari activity log
    // (tab Info), agar bentuk Task yang dihasilkan konsisten. Identitasnya harus
    // stabil karena dipakai `useTaskDeepLink` sebagai dependency.
    const taskMapContext = useMemo(
        () => ({
            assigneeSource: 'project' as const,
            dateFallback: 'empty-string' as const,
            project: {
                id: project.id.toString(),
                groupId: '',
                projectName: project.name,
                description: project.description || '',
                progressStatus: project.status as Status,
                creatorId: '',
                deadline: project.due_date || '',
                createdAt: '',
                updatedAt: '',
            },
            timestampSource: 'empty-string' as const,
        }),
        // Dep-nya nilai, bukan objek `project`: polling 10 detik mengirim objek
        // baru tiap putaran, dan identitas memo yang ikut berganti membuat
        // `fetchTaskById` mengambil ulang task deep-link terus-menerus.
        [
            project.id,
            project.name,
            project.description,
            project.status,
            project.due_date,
        ],
    );

    const adaptedTasks = mapApiTasksToTaskoTasks(
        tasks.data || [],
        taskMapContext,
    );

    // Deep-link `?task=<id>` dari klik notifikasi lonceng. Tab default halaman
    // ini sudah `tasks`, jadi TaskList selalu ter-mount saat deep-link dibuka.
    const {
        taskId: taskIdFromUrl,
        fetchTaskById,
        clearTaskQuery,
    } = useTaskDeepLink(taskMapContext);

    // Task yang dibuka dari batang Gantt. Disimpan sebagai state, bukan ditulis
    // ke `?task=`: query itu jalur Inertia, dan menuliskannya berarti kunjungan
    // penuh yang justru menjatuhkan prop `gantt` yang baru saja dipakai. Sheet
    // detailnya sendiri tetap milik TaskList — task yang tidak termuat di
    // halaman aktif diambil `fetchTaskById`, sama seperti deep-link lonceng.
    const [taskIdFromGantt, setTaskIdFromGantt] = useState<string | null>(null);

    const openTaskFromGantt = (taskId: number) => {
        setTaskIdFromGantt(String(taskId));
    };

    // useCallback wajib, bukan kerapian: identitas prop ini ikut menentukan
    // dependency efek pengambil task di TaskList. Sebagai arrow inline ia lahir
    // baru tiap render, dan efek itu akan menembakkan `fetchTaskById` berulang
    // untuk task yang tidak termuat di halaman aktif — persis task yang datang
    // dari batang Gantt.
    const handleTaskSheetClose = useCallback(() => {
        setTaskIdFromGantt(null);
        clearTaskQuery();
    }, [clearTaskQuery]);

    const allProjectsData = [
        {
            id: project.id.toString(),
            name: project.name,
            divisionId: project.division_id?.toString() || '',
            members: (project.members || []).map((m) => ({
                id: m.user_id.toString(),
                name: m.user?.name || 'Unknown',
                role: m.role,
            })),
        },
    ];

    const adaptedMembers = (project.members || []).map((member) => {
        const nameParts = (member.user?.name || 'User').split(' ');

        return {
            id: member.id.toString(),
            userId: member.user_id.toString(),
            role: member.role,
            user: {
                firstName: nameParts[0] || '',
                lastName: nameParts.slice(1).join(' ') || '',
                avatar: member.user?.avatar ?? null,
            },
        };
    });

    const handleEditRole = (member: ProjectTeamMember) => {
        setSelectedMember(member);
        setIsEditRoleOpen(true);
    };

    const handleRemoveMember = (member: ProjectTeamMember) => {
        setSelectedMember(member);
        setIsRemoveMemberOpen(true);
    };

    const adaptedProject = {
        id: project.id,
        projectName: project.name,
        description: project.description || '',
        progressStatus: project.status,
        overviews: project.description, // Use description as overviews for now
        deadline: project.due_date || '',
        members: adaptedMembers,
        tasks: adaptedTasks,
        activities: activities,
    };

    return (
        <>
            <Head title={`${project.name}`} />

            <div className="flex min-h-full flex-col bg-muted/50">
                {/* Project Header */}
                <div className="border-b bg-background px-4 py-12 md:px-8 md:py-16">
                    <div className="max-w-8xl mx-auto">
                        <div className="flex flex-col justify-between gap-6 md:flex-row md:items-center">
                            <div className="flex items-start gap-4">
                                <div className="flex h-12 w-12 shrink-0 items-center justify-center rounded-2xl bg-primary text-primary-foreground shadow-sm md:h-14 md:w-14">
                                    <FolderKanban className="h-6 w-6 md:h-7 md:w-7" />
                                </div>
                                <div className="min-w-0 flex-1">
                                    <h1 className="truncate text-2xl font-extrabold tracking-tight md:text-3xl">
                                        {project.name}
                                    </h1>
                                    <p className="mt-1 line-clamp-2 text-sm text-muted-foreground md:text-base">
                                        {project.description}
                                    </p>
                                </div>
                            </div>
                            <div className="flex items-center gap-3">
                                <div className="flex items-center rounded-xl border bg-background/50 p-1 shadow-xs">
                                    {/* Current Status Info */}
                                    <div
                                        className={`flex items-center gap-2 rounded-lg px-3 py-1.5 text-xs font-bold tracking-wide uppercase transition-all duration-300 ${
                                            PROJECT_STATUS_MAP[currentStatus]
                                                ?.color || 'bg-muted'
                                        }`}
                                    >
                                        <span className="relative flex h-2 w-2">
                                            {currentStatus !== 'completed' && (
                                                <span
                                                    className={`absolute inline-flex h-full w-full animate-ping rounded-full opacity-75 ${
                                                        PROJECT_STATUS_MAP[
                                                            currentStatus
                                                        ]?.ping || 'bg-primary'
                                                    }`}
                                                ></span>
                                            )}
                                            <span
                                                className={`relative inline-flex h-2 w-2 rounded-full ${
                                                    PROJECT_STATUS_MAP[
                                                        currentStatus
                                                    ]?.dot || 'bg-primary'
                                                }`}
                                            ></span>
                                        </span>
                                        {PROJECT_STATUS_MAP[currentStatus]
                                            ?.label || currentStatus}
                                    </div>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>

                {/* Main Content Area */}
                <div className="max-w-8xl mx-auto w-full p-4 md:p-8">
                    <Tabs
                        value={activeTab}
                        onValueChange={handleTabChange}
                        className="space-y-8"
                    >
                        <TabsList className="h-auto w-full justify-start gap-6 overflow-x-auto rounded-none border-b bg-transparent p-0">
                            <TabsTrigger
                                value="tasks"
                                className="relative flex items-center gap-2 rounded-none border-b-2 border-transparent px-0 pt-2 pb-4 text-sm font-semibold whitespace-nowrap transition-all data-[state=active]:border-foreground data-[state=active]:bg-transparent data-[state=active]:text-foreground data-[state=active]:shadow-none"
                            >
                                <CheckCircle2 size={16} />
                                Tasks
                            </TabsTrigger>
                            <TabsTrigger
                                value="gantt"
                                className="relative flex items-center gap-2 rounded-none border-b-2 border-transparent px-0 pt-2 pb-4 text-sm font-semibold whitespace-nowrap transition-all data-[state=active]:border-foreground data-[state=active]:bg-transparent data-[state=active]:text-foreground data-[state=active]:shadow-none"
                            >
                                <CalendarClock size={16} />
                                Gantt
                            </TabsTrigger>
                            <TabsTrigger
                                value="team"
                                className="relative flex items-center gap-2 rounded-none border-b-2 border-transparent px-0 pt-2 pb-4 text-sm font-semibold whitespace-nowrap transition-all data-[state=active]:border-foreground data-[state=active]:bg-transparent data-[state=active]:text-foreground data-[state=active]:shadow-none"
                            >
                                <Users size={16} />
                                Team
                            </TabsTrigger>
                            <TabsTrigger
                                value="info"
                                className="relative flex items-center gap-2 rounded-none border-b-2 border-transparent px-0 pt-2 pb-4 text-sm font-semibold whitespace-nowrap transition-all data-[state=active]:border-foreground data-[state=active]:bg-transparent data-[state=active]:text-foreground data-[state=active]:shadow-none"
                            >
                                <Info size={16} />
                                Info
                            </TabsTrigger>
                            {(can.update || can.delete || can.duplicate) && (
                                <TabsTrigger
                                    value="settings"
                                    className="relative flex items-center gap-2 rounded-none border-b-2 border-transparent px-0 pt-2 pb-4 text-sm font-semibold whitespace-nowrap transition-all data-[state=active]:border-foreground data-[state=active]:bg-transparent data-[state=active]:text-foreground data-[state=active]:shadow-none"
                                >
                                    <Settings size={16} />
                                    Settings
                                </TabsTrigger>
                            )}
                        </TabsList>

                        <div>
                            <div>
                                {/* `forceMount`: sheet detail task milik
                                    TaskList, dan batang Gantt membukanya tanpa
                                    memindahkan tab. Sheet-nya sendiri dirender
                                    ke portal, jadi tetap tampil penuh walau
                                    panel induknya sedang disembunyikan —
                                    TaskList hanya perlu tetap hidup untuk
                                    menampungnya. */}
                                <TabsContent
                                    value="tasks"
                                    forceMount
                                    className={
                                        activeTab === 'tasks'
                                            ? 'mt-0'
                                            : 'mt-0 hidden'
                                    }
                                >
                                    <TaskList
                                        onSheetOpenChange={setIsTaskSheetOpen}
                                        tasks={adaptedTasks}
                                        pagination={tasks}
                                        summary={taskSummary}
                                        projectUrl={projectShowUrl}
                                        allProjects={allProjectsData}
                                        can={can}
                                        currentUserId={currentUserId}
                                        initialViewingTaskId={
                                            taskIdFromUrl ?? taskIdFromGantt
                                        }
                                        fetchTaskById={fetchTaskById}
                                        onSheetClose={handleTaskSheetClose}
                                    />
                                </TabsContent>

                                <TabsContent value="gantt" className="mt-0">
                                    <ProjectGantt
                                        data={gantt}
                                        canManage={can.manageTasks}
                                        onOpenTask={openTaskFromGantt}
                                    />
                                </TabsContent>

                                <TabsContent value="team" className="mt-0">
                                    <ProjectTeam
                                        members={adaptedMembers}
                                        onAddMember={() =>
                                            setIsAddMemberOpen(true)
                                        }
                                        onEditRole={handleEditRole}
                                        onRemoveMember={handleRemoveMember}
                                        currentUserId={currentUserId}
                                        can={can}
                                    />
                                </TabsContent>

                                <TabsContent value="info" className="mt-0">
                                    <ProjectInfo
                                        project={adaptedProject}
                                        taskProject={taskMapContext.project}
                                        divisionId={
                                            allProjectsData[0]?.divisionId
                                        }
                                        projectMembers={
                                            allProjectsData[0]?.members
                                        }
                                        taskSummary={taskSummary}
                                        memberCount={adaptedMembers.length}
                                    />
                                </TabsContent>

                                {(can.update ||
                                    can.delete ||
                                    can.duplicate) && (
                                    <TabsContent
                                        value="settings"
                                        className="mt-0"
                                    >
                                        <ProjectSettings
                                            onEdit={() => setIsEditOpen(true)}
                                            onDuplicate={() =>
                                                setIsDuplicateOpen(true)
                                            }
                                            onDelete={() =>
                                                setIsDeleteOpen(true)
                                            }
                                            can={can}
                                            projectStatus={currentStatus}
                                            onUpdateStatus={handleUpdateStatus}
                                        />
                                    </TabsContent>
                                )}
                            </div>
                        </div>
                    </Tabs>
                </div>
            </div>

            <EditProjectDialog
                project={adaptedProject}
                open={isEditOpen}
                onOpenChange={setIsEditOpen}
                hasIncompleteTasks={hasIncompleteTasks}
                hasStartedTasks={hasStartedTasks}
            />
            <DuplicateProjectDialog
                project={project}
                open={isDuplicateOpen}
                onOpenChange={setIsDuplicateOpen}
            />
            <DeleteProjectDialog
                project={adaptedProject}
                open={isDeleteOpen}
                onOpenChange={setIsDeleteOpen}
            />
            <AddMemberDialog
                projectId={project.id}
                existingMemberIds={project.members?.map((m) => m.user_id) || []}
                open={isAddMemberOpen}
                onOpenChange={setIsAddMemberOpen}
            />
            <EditMemberRoleDialog
                projectId={project.id}
                member={selectedMember}
                open={isEditRoleOpen}
                onOpenChange={setIsEditRoleOpen}
            />
            <RemoveMemberDialog
                projectId={project.id}
                member={selectedMember}
                open={isRemoveMemberOpen}
                onOpenChange={setIsRemoveMemberOpen}
            />
        </>
    );
}
