"use client";

import React, { useRef, useEffect, useState } from "react";
import { useEditorStore, Page } from "@/lib/store";
import {
    Search,
    PanelLeftClose,
    Sun,
    Moon,
    Upload,
    Loader2,
    FolderPlus,
    FilePlus,
    Settings,
    Hash,
    Tag as TagIcon,
    FileText,
    Folder,
    LogOut,
    ChevronRight,
    ChevronDown,
    Layers,
    PanelLeftOpen,
    SlidersHorizontal,
} from "lucide-react";
import { useTheme } from "next-themes";
import { TreeView } from "./sidebar/tree-view";
import Link from "next/link";
import { useRouter } from "next/navigation";
import { cn, getTagColor } from "@/lib/utils";
import { useSearchStore } from "@/lib/search-store";
import { useImport } from "@/components/import-context";
import {
    DndContext,
    DragEndEvent,
    DragOverlay,
    useSensor,
    useSensors,
    PointerSensor,
    pointerWithin,
    DragStartEvent,
    useDroppable,
} from "@dnd-kit/core";
import { arrayMove } from "@dnd-kit/sortable";

function RootDropZone() {
    const { setNodeRef, isOver } = useDroppable({ id: "root-drop-zone" });

    return (
        <div
            ref={setNodeRef}
            className={cn(
                "mt-2 flex min-h-[42px] items-center justify-center rounded-lg border border-dashed text-xs transition-all",
                isOver
                    ? "border-primary/40 bg-primary/10 text-primary"
                    : "border-transparent text-muted-foreground/0 hover:border-border/60 hover:text-muted-foreground/70"
            )}
        >
            {isOver ? "移动到根目录" : "拖拽到此处移到根目录"}
        </div>
    );
}

export function ResizableSidebar() {
    const [width, setWidth] = useState(280);
    const [isCollapsed, setIsCollapsed] = useState(false);
    const [isResizing, setIsResizing] = useState(false);
    const sidebarRef = useRef<HTMLElement>(null);

    useEffect(() => {
        localStorage.setItem("sidebar-width", width.toString());
        localStorage.setItem("sidebar-collapsed", isCollapsed.toString());
    }, [width, isCollapsed]);

    const startResizing = React.useCallback(() => {
        setIsResizing(true);
    }, []);

    const stopResizing = React.useCallback(() => {
        setIsResizing(false);
    }, []);

    const resize = React.useCallback(
        (mouseMoveEvent: MouseEvent) => {
            if (!isResizing) return;
            const newWidth = mouseMoveEvent.clientX;
            if (newWidth >= 240 && newWidth <= 500) {
                setWidth(newWidth);
            }
        },
        [isResizing]
    );

    useEffect(() => {
        window.addEventListener("mousemove", resize);
        window.addEventListener("mouseup", stopResizing);
        return () => {
            window.removeEventListener("mousemove", resize);
            window.removeEventListener("mouseup", stopResizing);
        };
    }, [resize, stopResizing]);

    return (
        <aside
            ref={sidebarRef}
            className={cn(
                "group/sidebar relative z-20 hidden h-screen flex-col border-r bg-secondary/80 backdrop-blur-sm md:flex",
                isResizing ? "transition-none" : "transition-[width] duration-300 ease-in-out",
                isCollapsed && "w-[0px] border-none"
            )}
            style={{ width: isCollapsed ? 0 : width }}
        >
            <button
                onClick={() => setIsCollapsed(!isCollapsed)}
                className={cn(
                    "absolute -right-3 top-6 z-50 rounded-full border bg-card p-1 text-foreground shadow-sm transition-all opacity-100 lg:opacity-0 lg:group-hover/sidebar:opacity-100 hover:bg-primary hover:text-primary-foreground",
                    isCollapsed && "-right-8 opacity-100"
                )}
                title={isCollapsed ? "展开侧边栏" : "收起侧边栏"}
            >
                {isCollapsed ? <PanelLeftOpen size={14} /> : <PanelLeftClose size={14} />}
            </button>

            <div className={cn("flex flex-1 flex-col overflow-hidden", isCollapsed ? "hidden" : "visible")}>
                <SidebarContent />
            </div>

            {!isCollapsed && (
                <div
                    className="absolute right-0 top-0 z-40 h-full w-1 cursor-col-resize transition-colors hover:bg-primary/50"
                    onMouseDown={startResizing}
                />
            )}
        </aside>
    );
}

export function SidebarContent({ onCloseMobile }: { onCloseMobile?: () => void }) {
    const { pages, activePageId, fetchPages, addPage, isLoading, movePage, reorderPages } = useEditorStore();
    const { setOpen, openSearchWithTag } = useSearchStore();
    const { triggerImport, isImporting } = useImport();
    const { theme, setTheme } = useTheme();
    const router = useRouter();
    const [mounted, setMounted] = React.useState(false);

    const [isWorkspaceOpen, setIsWorkspaceOpen] = React.useState(true);
    const [isFilterOpen, setIsFilterOpen] = React.useState(false);
    const [expandedMap, setExpandedMap] = React.useState<Record<string, boolean>>(() => {
        if (typeof window === "undefined") return {};
        try {
            const raw = localStorage.getItem("noteai-tree-expanded");
            if (!raw) return {};
            const parsed = JSON.parse(raw);
            if (!parsed || typeof parsed !== "object") return {};
            return parsed as Record<string, boolean>;
        } catch {
            return {};
        }
    });

    React.useEffect(() => {
        setMounted(true);
    }, []);

    React.useEffect(() => {
        if (typeof window === "undefined") return;
        try {
            localStorage.setItem("noteai-tree-expanded", JSON.stringify(expandedMap));
        } catch {
            // ignore storage errors
        }
    }, [expandedMap]);

    React.useEffect(() => {
        if (!activePageId) return;
        const current = pages.find((p) => p.id === activePageId);
        if (!current) return;

        const ancestors: string[] = [];
        let cursor = current.parentId;
        while (cursor) {
            ancestors.push(cursor);
            cursor = pages.find((p) => p.id === cursor)?.parentId ?? null;
        }
        if (ancestors.length === 0) return;
        setExpandedMap((prev) => {
            const next = { ...prev };
            ancestors.forEach((id) => {
                next[id] = true;
            });
            return next;
        });
    }, [activePageId, pages]);

    const toggleExpand = React.useCallback((id: string) => {
        setExpandedMap((prev) => ({ ...prev, [id]: !prev[id] }));
    }, []);

    const allTags = Array.from(new Set(pages.flatMap((p) => p.tags || []))).sort((a, b) => a.localeCompare(b));

    const handleLogout = async () => {
        try {
            await fetch("/api/auth/logout", { method: "POST" });
            router.push("/login");
            router.refresh();
        } catch (error) {
            console.error("Logout failed", error);
            router.push("/login");
        }
    };

    const sensors = useSensors(
        useSensor(PointerSensor, {
            activationConstraint: {
                distance: 8,
            },
        })
    );

    const handleDragEnd = (event: DragEndEvent) => {
        const { active, over } = event;
        if (!over) return;

        const activeId = active.id as string;
        const overId = over.id as string;
        if (activeId === overId) return;

        if (overId === "root-drop-zone") {
            movePage(activeId, null);
            return;
        }

        const activeNode = pages.find((p) => p.id === activeId);
        const overNode = pages.find((p) => p.id === overId);
        if (!activeNode || !overNode) return;

        if (activeNode.type === "file" && overNode.type === "folder" && activeNode.parentId !== overNode.id) {
            movePage(activeId, overId);
            return;
        }

        const isSameParent = activeNode.parentId === overNode.parentId;
        if (isSameParent) {
            const siblings = pages
                .filter((p) => p.parentId === activeNode.parentId)
                .sort((a, b) => (a.order || 0) - (b.order || 0));
            const oldIndex = siblings.findIndex((p) => p.id === activeId);
            const newIndex = siblings.findIndex((p) => p.id === overId);
            if (oldIndex !== newIndex) {
                const newOrder = arrayMove(siblings, oldIndex, newIndex);
                const updates = newOrder.map((p, index) => ({ id: p.id, order: index }));
                reorderPages(updates);
            }
        } else if (overNode.type === "folder") {
            movePage(activeId, overId);
        } else {
            movePage(activeId, overNode.parentId);
        }
    };

    const [activeDragItem, setActiveDragItem] = React.useState<Page | null>(null);

    const onDragStart = (event: DragStartEvent) => {
        const item = pages.find((p) => p.id === event.active.id);
        if (item) setActiveDragItem(item);
    };

    useEffect(() => {
        fetchPages();
    }, [fetchPages]);

    const handleItemClick = () => {
        if (onCloseMobile) onCloseMobile();
    };

    return (
        <div className="flex h-full flex-col">
            <div className="space-y-3 border-b border-border/60 bg-muted/[0.18] p-3">
                <div className="flex items-center justify-between">
                    <div className="flex items-center gap-2">
                        <div className="flex h-7 w-7 items-center justify-center rounded-md bg-primary text-[10px] font-bold text-primary-foreground">AI</div>
                        <div>
                            <div className="text-sm font-semibold tracking-tight text-foreground">NoteAI</div>
                            <div className="text-[10px] text-muted-foreground">Workspace</div>
                        </div>
                    </div>
                    <div className="flex items-center gap-1">
                        <button
                            onClick={() => addPage(null, "file")}
                            className="ui-btn-secondary h-10 px-2 text-xs md:h-8 md:w-8 md:px-0"
                            title="新建文件"
                        >
                            <span className="sr-only">新建文件</span>
                            <FilePlus size={15} />
                            <span className="md:hidden">文件</span>
                        </button>
                        <button
                            onClick={() => addPage(null, "folder")}
                            className="ui-btn-secondary h-10 px-2 text-xs md:h-8 md:w-8 md:px-0"
                            title="新建文件夹"
                        >
                            <span className="sr-only">新建文件夹</span>
                            <FolderPlus size={15} />
                            <span className="md:hidden">文件夹</span>
                        </button>
                        <button
                            onClick={() => {
                                setOpen(true);
                                handleItemClick();
                            }}
                            className="ui-btn-secondary h-10 px-2 text-xs md:h-8 md:w-8 md:px-0"
                            title="搜索文档 (Ctrl+K)"
                            aria-label="搜索文档"
                        >
                            <Search size={15} />
                            <span className="md:hidden">搜索</span>
                        </button>
                        {onCloseMobile && (
                            <button
                                onClick={onCloseMobile}
                                className="ui-icon-btn h-10 w-10 hover:text-destructive md:h-8 md:w-8"
                                title="关闭菜单"
                            >
                                <span className="sr-only">关闭菜单</span>
                                <PanelLeftClose size={16} />
                            </button>
                        )}
                    </div>
                </div>

                <button
                    onClick={() => setIsFilterOpen((v) => !v)}
                    className="flex h-11 w-full items-center justify-between rounded-md px-2 text-xs font-medium text-foreground/80 transition-colors hover:bg-muted/60 hover:text-foreground md:h-9"
                >
                    <span className="flex items-center gap-1.5">
                        <SlidersHorizontal size={13} />
                        筛选器
                    </span>
                    {isFilterOpen ? <ChevronDown size={14} /> : <ChevronRight size={14} />}
                </button>

                {isFilterOpen && (
                    <div className="rounded-lg border border-border/60 bg-background/40 p-2">
                        <div className="mb-1 flex items-center gap-1 text-[11px] text-muted-foreground">
                            <TagIcon size={12} />
                            标签筛选
                        </div>
                        <div className="flex max-h-24 flex-wrap gap-1 overflow-y-auto pr-1">
                            {allTags.length > 0 ? (
                                allTags.map((tag) => {
                                    const colors = getTagColor(tag);
                                    return (
                                        <button
                                            key={tag}
                                            onClick={() => {
                                                openSearchWithTag(tag);
                                                setOpen(true);
                                                handleItemClick();
                                            }}
                                            className={cn(
                                                "inline-flex items-center gap-1 rounded-[4px] border px-2 py-0.5 text-[10px] font-medium shadow-sm transition-transform duration-150 hover:scale-[1.02]",
                                                colors.bg,
                                                colors.text,
                                                colors.border
                                            )}
                                            title={`按标签筛选：${tag}`}
                                        >
                                            <Hash size={10} className="opacity-70" />
                                            {tag}
                                        </button>
                                    );
                                })
                            ) : (
                                <span className="text-[10px] italic text-muted-foreground/70">暂无标签</span>
                            )}
                        </div>
                    </div>
                )}
            </div>

            <div className="flex min-h-0 flex-1 flex-col p-2">
                <button
                    onClick={() => setIsWorkspaceOpen(!isWorkspaceOpen)}
                    className="mb-1 flex h-11 w-full items-center justify-between rounded-lg px-2 text-sm font-semibold uppercase tracking-wide text-foreground/85 transition-colors hover:bg-muted/60 hover:text-foreground md:h-9 md:text-xs"
                >
                    <span className="flex items-center gap-1.5">
                        <Layers size={13} className="opacity-80" />
                        文档
                        <span className="rounded bg-muted px-1.5 py-0.5 text-[10px] text-muted-foreground">{pages.length}</span>
                    </span>
                    {isWorkspaceOpen ? <ChevronDown size={14} /> : <ChevronRight size={14} />}
                </button>

                {isWorkspaceOpen && (
                    <>
                        {isLoading ? (
                            <div className="space-y-2 px-1 py-2">
                                <div className="rounded-lg border border-border/50 bg-background/35 p-2">
                                    <div className="h-4 w-1/3 animate-pulse rounded bg-muted/60" />
                                    <div className="mt-2 h-7 animate-pulse rounded-md bg-muted/55" />
                                    <div className="mt-1.5 h-7 animate-pulse rounded-md bg-muted/45" />
                                    <div className="mt-1.5 h-7 animate-pulse rounded-md bg-muted/35" />
                                </div>
                            </div>
                        ) : pages.length === 0 ? (
                            <div className="ui-card mt-2 flex flex-col items-center gap-2 px-3 py-6 text-center text-xs text-muted-foreground">
                                <FileText size={18} className="text-muted-foreground/70" />
                                <p>还没有文档</p>
                                <button onClick={() => addPage(null, "file")} className="text-primary hover:underline">
                                    新建第一页
                                </button>
                            </div>
                        ) : (
                            <DndContext
                                sensors={sensors}
                                collisionDetection={pointerWithin}
                                onDragStart={onDragStart}
                                onDragEnd={handleDragEnd}
                            >
                                <div
                                    onClick={handleItemClick}
                                    className="min-h-0 flex-1 overflow-y-auto rounded-lg bg-background/15 p-0.5 pr-0.5"
                                >
                                    <TreeView
                                        pages={pages}
                                        parentId={null}
                                        expanded={expandedMap}
                                        toggleExpand={toggleExpand}
                                        folderFileCount={{}}
                                    />
                                    <RootDropZone />
                                </div>
                                <DragOverlay>
                                    {activeDragItem ? (
                                        <div className="flex items-center gap-2 rounded-md border bg-popover px-2 py-1 text-sm opacity-95 shadow-lg">
                                            {activeDragItem.icon ? (
                                                <span className="flex h-4 w-4 items-center justify-center text-[16px] leading-none grayscale-[0.2]">{activeDragItem.icon}</span>
                                            ) : activeDragItem.type === "folder" ? (
                                                <Folder size={16} className="shrink-0 fill-indigo-500/20 text-indigo-500" />
                                            ) : (
                                                <FileText size={16} className="shrink-0 text-muted-foreground/70" />
                                            )}
                                            {activeDragItem.title}
                                        </div>
                                    ) : null}
                                </DragOverlay>
                            </DndContext>
                        )}
                    </>
                )}
            </div>

            <div className="border-t border-border/60 bg-muted/[0.22] p-3 backdrop-blur-sm">
                <div className="flex items-center justify-between rounded-xl border border-border/60 bg-background/45 px-2 py-1">
                    <span className="px-1 text-[11px] text-muted-foreground">系统</span>
                    <div className="flex items-center gap-1">
                        <button
                            onClick={() => triggerImport(null)}
                            disabled={isImporting}
                            aria-busy={isImporting}
                            className="ui-icon-btn h-10 w-10 md:h-8 md:w-8"
                            title={isImporting ? "导入中..." : "导入"}
                        >
                            <span className="sr-only">{isImporting ? "导入中" : "导入"}</span>
                            {isImporting ? <Loader2 size={15} className="animate-spin" /> : <Upload size={15} />}
                        </button>
                        <Link
                            href="/settings"
                            onClick={handleItemClick}
                            className="ui-icon-btn h-10 w-10 md:h-8 md:w-8"
                            title="设置"
                            aria-label="设置"
                        >
                            <Settings size={15} />
                        </Link>
                        <button
                            onClick={() => setTheme(theme === "dark" ? "light" : "dark")}
                            className="ui-icon-btn h-10 w-10 md:h-8 md:w-8"
                            title={mounted ? (theme === "dark" ? "切换到明亮模式" : "切换到暗黑模式") : "切换主题"}
                        >
                            <span className="sr-only">{mounted ? (theme === "dark" ? "切换到明亮模式" : "切换到暗黑模式") : "切换主题"}</span>
                            {mounted ? (theme === "dark" ? <Sun size={15} /> : <Moon size={15} />) : <Moon size={15} />}
                        </button>
                        <button
                            onClick={handleLogout}
                            className="ui-icon-btn h-10 w-10 hover:text-destructive md:h-8 md:w-8"
                            title="退出登录"
                        >
                            <span className="sr-only">退出登录</span>
                            <LogOut size={15} />
                        </button>
                    </div>
                </div>
            </div>
        </div>
    );
}
