"use client";
import { useState, useCallback, useEffect, useRef } from "react";
import { Sidebar } from "./Sidebar";
import { TaskList, Task, List, User } from "../tasks/TaskList";
import { useUserPrefs, usePrefsStyle } from "@/lib/useUserPrefs";
import { TaskDetail } from "../tasks/TaskDetail";
import { CommandPalette } from "../ui/CommandPalette";
import {
  getDemoStore,
  saveDemoStore,
  MockList,
  MockTask,
  MockTag,
  updateTaskInTree,
  moveToTrashInTree,
  restoreTaskInTree,
  deleteTaskInTree,
  emptyTrashInTree,
  addTaskToTree,
  findTaskInTree,
  getAllTrashTasks,
  filterTasksByTag,
} from "@/lib/mockData";

interface AppShellProps {
  user: User;
  isDemo?: boolean;
}

export function AppShell({ user, isDemo = false }: AppShellProps) {
  const [lists, setLists] = useState<List[]>(() => {
    if (isDemo && typeof window !== "undefined") {
      return getDemoStore().lists as List[];
    }
    return [];
  });
  const [selectedListId, setSelectedListId] = useState<string | null>(() => {
    if (isDemo && typeof window !== "undefined") {
      const storeLists = getDemoStore().lists;
      return storeLists.length > 0 ? storeLists[0].id : null;
    }
    return null;
  });
  const [selectedTag, setSelectedTag] = useState<string | null>(null);
  const [isTrashActive, setIsTrashActive] = useState(false);
  const [selectedTask, setSelectedTask] = useState<Task | null>(null);
  const [tasks, setTasks] = useState<Task[]>(() => {
    if (isDemo && typeof window !== "undefined") {
      const store = getDemoStore();
      const firstListId = store.lists[0]?.id;
      return (store.tasks as Task[]).filter((t) => !t.isDeleted && t.listId === firstListId && !t.completed);
    }
    return [];
  });
  const [sidebarOpen, setSidebarOpen] = useState(false);
  const [showCompleted, setShowCompleted] = useState(false);
  const [cmdPaletteOpen, setCmdPaletteOpen] = useState(false);
  const [refreshKey, setRefreshKey] = useState(0);

  // Global user preferences (reactive)
  const { prefs, updatePrefs } = useUserPrefs();
  const prefsStyle = usePrefsStyle(prefs);

  // Sidebar resize drag
  const sidebarResizing = useRef(false);
  const handleSidebarResizeStart = (e: React.MouseEvent) => {
    e.preventDefault();
    sidebarResizing.current = true;
    document.body.style.cursor = "col-resize";
    document.body.style.userSelect = "none";

    const onMove = (ev: MouseEvent) => {
      if (!sidebarResizing.current) return;
      const newW = Math.max(160, Math.min(420, ev.clientX));
      updatePrefs({ sidebarWidth: newW });
    };
    const onUp = () => {
      sidebarResizing.current = false;
      document.body.style.cursor = "";
      document.body.style.userSelect = "";
      window.removeEventListener("mousemove", onMove);
      window.removeEventListener("mouseup", onUp);
    };
    window.addEventListener("mousemove", onMove);
    window.addEventListener("mouseup", onUp);
  };

  // Detail panel resize drag
  const detailResizing = useRef(false);
  const handleDetailResizeStart = (e: React.MouseEvent) => {
    e.preventDefault();
    detailResizing.current = true;
    document.body.style.cursor = "col-resize";
    document.body.style.userSelect = "none";

    const onMove = (ev: MouseEvent) => {
      if (!detailResizing.current) return;
      const newW = Math.max(300, Math.min(760, window.innerWidth - ev.clientX));
      updatePrefs({ detailWidth: newW });
    };
    const onUp = () => {
      detailResizing.current = false;
      document.body.style.cursor = "";
      document.body.style.userSelect = "";
      window.removeEventListener("mousemove", onMove);
      window.removeEventListener("mouseup", onUp);
    };
    window.addEventListener("mousemove", onMove);
    window.addEventListener("mouseup", onUp);
  };

  // Listen for Ctrl+K event
  useEffect(() => {
    const handler = () => setCmdPaletteOpen(true);
    document.addEventListener("checkflow:openCommandPalette", handler);
    return () => document.removeEventListener("checkflow:openCommandPalette", handler);
  }, []);

  // Demo tasks filter & reconstruct hierarchical structure
  useEffect(() => {
    if (isDemo) {
      const store = getDemoStore();
      setLists(store.lists);
      if (isTrashActive) {
        setTasks(getAllTrashTasks(store.tasks) as Task[]);
      } else if (selectedTag) {
        setTasks(filterTasksByTag(store.tasks, selectedTag) as Task[]);
      } else if (selectedListId) {
        const listTasks = (store.tasks as Task[]).filter(
          (t) => !t.isDeleted && t.listId === selectedListId && (showCompleted ? true : !t.completed)
        );
        setTasks(listTasks);
      }
    }
  }, [isDemo, selectedListId, isTrashActive, selectedTag, showCompleted, refreshKey]);

  const refresh = useCallback(() => setRefreshKey((k) => k + 1), []);

  const handleTaskSelect = useCallback((task: Task | null) => {
    setSelectedTask(task);
  }, []);

  // Update a task in full tree (supports unlimited N-depth nesting)
  const handleTaskUpdate = useCallback((updated: Task) => {
    setTasks((prev) => updateTaskInTree(prev as MockTask[], updated as MockTask) as Task[]);
    setSelectedTask((prev) => {
      if (prev && prev.id === updated.id) {
        return { ...updated, children: updated.children || prev.children || [] };
      }
      return prev;
    });
  }, []);

  const handleListSelect = useCallback((id: string) => {
    setIsTrashActive(false);
    setSelectedTag(null);
    setSelectedListId(id);
    setSelectedTask(null);
    setSidebarOpen(false);
  }, []);

  const handleTagSelect = useCallback((tagName: string | null) => {
    setIsTrashActive(false);
    setSelectedTag(tagName);
    setSelectedTask(null);
    setSidebarOpen(false);
  }, []);

  const handleTrashSelect = useCallback(() => {
    setIsTrashActive(true);
    setSelectedTag(null);
    setSelectedListId(null);
    setSelectedTask(null);
    setSidebarOpen(false);
  }, []);

  // Update List Name
  const handleUpdateListName = async (id: string, newName: string) => {
    const trimmed = newName.trim();
    if (!trimmed) return;

    if (isDemo) {
      const store = getDemoStore();
      const newLists = store.lists.map((l) => (l.id === id ? { ...l, name: trimmed } : l));
      saveDemoStore(newLists, store.tasks);
      setLists(newLists);
      return;
    }

    try {
      const res = await fetch(`/api/lists/${id}`, {
        method: "PATCH",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ name: trimmed }),
      });
      if (res.ok) {
        const updated = await res.json();
        setLists((prev) => prev.map((l) => (l.id === id ? { ...l, name: updated.name } : l)));
      }
    } catch (err) {
      console.error("Failed to update list name", err);
    }
  };

  // Demo Handlers
  const handleDemoCreateList = (name: string, color: string) => {
    const newList: MockList = {
      id: "demo-list-" + Date.now(),
      name,
      color,
      icon: "list",
    };
    const store = getDemoStore();
    const newLists = [...store.lists, newList];
    saveDemoStore(newLists, store.tasks);
    setLists(newLists);
    setSelectedListId(newList.id);
  };

  const handleDemoDeleteList = (id: string) => {
    const store = getDemoStore();
    const newLists = store.lists.filter((l) => l.id !== id);
    const newTasks = store.tasks.filter((t) => t.listId !== id);
    saveDemoStore(newLists, newTasks);
    setLists(newLists);
    if (selectedListId === id) {
      setSelectedListId(newLists[0]?.id || null);
    }
    refresh();
  };

  const handleDemoAddTask = (
    title: string,
    listId: string,
    parentId: string | null = null,
    meta?: { dueDate?: string | null; priority?: number; tags?: { tag: MockTag }[] }
  ) => {
    const newTask: Task = {
      id: "demo-task-" + Date.now(),
      listId,
      parentId: parentId || null,
      title,
      note: null,
      completed: false,
      completedAt: null,
      dueDate: meta?.dueDate || null,
      priority: meta?.priority || 0,
      sortOrder: tasks.length,
      createdAt: new Date().toISOString(),
      updatedAt: new Date().toISOString(),
      deletedAt: null,
      isDeleted: false,
      children: [],
      tags: meta?.tags || [],
    };
    const store = getDemoStore();
    const newTasks = addTaskToTree(store.tasks, parentId, newTask as MockTask);
    saveDemoStore(store.lists, newTasks);

    setTasks((prev) => addTaskToTree(prev as MockTask[], parentId, newTask as MockTask) as Task[]);

    if (selectedTask && selectedTask.id === parentId) {
      setSelectedTask((prev) =>
        prev ? { ...prev, children: [...(prev.children || []), newTask] } : prev
      );
    }
    refresh();
  };

  const handleDemoToggleTask = (id: string, completed: boolean) => {
    const store = getDemoStore();
    const target = findTaskInTree(store.tasks, id);
    if (target) {
      const updated = {
        ...target,
        completed,
        completedAt: completed ? new Date().toISOString() : null,
      };
      const newTasks = updateTaskInTree(store.tasks, updated);
      saveDemoStore(store.lists, newTasks);
      setTasks((prev) =>
        (updateTaskInTree(prev as MockTask[], updated) as Task[]).filter((t) => showCompleted || !t.completed)
      );

      if (selectedTask) {
        const latestSelected = findTaskInTree(newTasks, selectedTask.id);
        if (latestSelected) {
          setSelectedTask(latestSelected as Task);
        }
      }
    }
    refresh();
  };

  const handleDemoUpdateTask = (updated: Task) => {
    const store = getDemoStore();
    const newTasks = updateTaskInTree(store.tasks, updated as MockTask);
    saveDemoStore(store.lists, newTasks);
    handleTaskUpdate(updated);
  };

  // Move to Trash (Soft Delete)
  const handleDemoDeleteTask = (id: string) => {
    const store = getDemoStore();
    const newTasks = moveToTrashInTree(store.tasks, id);
    saveDemoStore(store.lists, newTasks);
    setTasks((prev) => prev.filter((t) => t.id !== id));
    if (selectedTask?.id === id) {
      setSelectedTask(null);
    }
    refresh();
  };

  // Restore from Trash
  const handleRestoreTask = (id: string) => {
    if (isDemo) {
      const store = getDemoStore();
      const newTasks = restoreTaskInTree(store.tasks, id);
      saveDemoStore(store.lists, newTasks);
      setTasks((prev) => prev.filter((t) => t.id !== id));
      refresh();
    }
  };

  // Permanent Delete
  const handlePermanentDeleteTask = (id: string) => {
    if (isDemo) {
      const store = getDemoStore();
      const newTasks = deleteTaskInTree(store.tasks, id);
      saveDemoStore(store.lists, newTasks);
      setTasks((prev) => prev.filter((t) => t.id !== id));
      refresh();
    }
  };

  // Empty Trash
  const handleEmptyTrash = () => {
    if (!confirm("Permanently empty all items in trash?")) return;
    if (isDemo) {
      const store = getDemoStore();
      const newTasks = emptyTrashInTree(store.tasks);
      saveDemoStore(store.lists, newTasks);
      setTasks([]);
      refresh();
    }
  };

  const handleUpdateTaskTitle = async (taskId: string, newTitle: string) => {
    const trimmed = newTitle.trim();
    if (!trimmed) return;

    if (isDemo) {
      const store = getDemoStore();
      const target = findTaskInTree(store.tasks, taskId);
      if (target) {
        const updated = { ...target, title: trimmed };
        const newTasks = updateTaskInTree(store.tasks, updated);
        saveDemoStore(store.lists, newTasks);
        handleTaskUpdate(updated as Task);
      }
      return;
    }

    try {
      const res = await fetch(`/api/tasks/${taskId}`, {
        method: "PATCH",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ title: trimmed }),
      });
      if (res.ok) {
        const updated = await res.json();
        handleTaskUpdate(updated);
      }
    } catch (err) {
      console.error("Failed to update task title", err);
    }
  };

  return (
    <div className="app-layout">
      {/* Dynamic CSS variable injection from user prefs */}
      <style>{prefsStyle}</style>

      {/* Sidebar 모바일 오버레이 */}
      {sidebarOpen && (
        <div
          className="modal-overlay"
          style={{ zIndex: 25 }}
          onClick={() => setSidebarOpen(false)}
        />
      )}

      {/* 바텀시트 모바일 오버레이 — 태스크 상세 패널이 열릴 때 */}
      {selectedTask && (
        <div
          className="bottom-sheet-overlay"
          onClick={() => setSelectedTask(null)}
        />
      )}

      <Sidebar
        user={user}
        lists={lists}
        setLists={setLists}
        selectedListId={selectedListId}
        onListSelect={handleListSelect}
        selectedTag={selectedTag}
        onTagSelect={handleTagSelect}
        isTrashActive={isTrashActive}
        onTrashSelect={handleTrashSelect}
        mobileOpen={sidebarOpen}
        onClose={() => setSidebarOpen(false)}
        isDemo={isDemo}
        onDemoCreateList={handleDemoCreateList}
        onDemoDeleteList={handleDemoDeleteList}
      />

      {/* Sidebar resize handle */}
      <div
        className="sidebar-resize-handle"
        onMouseDown={handleSidebarResizeStart}
        title="Drag to resize sidebar"
        style={{
          width: 4,
          cursor: "col-resize",
          background: "transparent",
          flexShrink: 0,
          transition: "background var(--dur-fast)",
          position: "relative",
          zIndex: 10,
        }}
        onMouseEnter={(e) => { (e.currentTarget as HTMLElement).style.background = "var(--accent-medium)"; }}
        onMouseLeave={(e) => { (e.currentTarget as HTMLElement).style.background = "transparent"; }}
      />

      <div className="main-content">
        <TaskList
          key={`${selectedListId}-${isTrashActive}-${selectedTag}-${refreshKey}`}
          user={user}
          listId={selectedListId}
          lists={lists}
          tasks={tasks}
          setTasks={setTasks}
          selectedTaskId={selectedTask?.id ?? null}
          onTaskSelect={handleTaskSelect}
          showCompleted={showCompleted}
          onToggleCompleted={() => setShowCompleted((p) => !p)}
          onMenuOpen={() => setSidebarOpen(true)}
          onRefresh={refresh}
          isDemo={isDemo}
          isTrashActive={isTrashActive}
          selectedTag={selectedTag}
          onEmptyTrash={handleEmptyTrash}
          onRestoreTask={handleRestoreTask}
          onPermanentDeleteTask={handlePermanentDeleteTask}
          onDemoAddTask={handleDemoAddTask}
          onDemoToggleTask={handleDemoToggleTask}
          onUpdateTaskTitle={handleUpdateTaskTitle}
          onUpdateListName={handleUpdateListName}
          onDeleteTask={isDemo ? handleDemoDeleteTask : async (id: string) => {
            await fetch(`/api/tasks/${id}`, { method: "DELETE" });
            refresh();
          }}
        />
      </div>

      {selectedTask && (
        <>
          {/* Detail panel resize handle (left edge) */}
          <div
            onMouseDown={handleDetailResizeStart}
            title="Drag to resize detail panel"
            style={{
              width: 4,
              cursor: "col-resize",
              background: "transparent",
              flexShrink: 0,
              zIndex: 10,
              transition: "background var(--dur-fast)",
            }}
            onMouseEnter={(e) => { (e.currentTarget as HTMLElement).style.background = "var(--accent-medium)"; }}
            onMouseLeave={(e) => { (e.currentTarget as HTMLElement).style.background = "transparent"; }}
          />
          <TaskDetail
            task={selectedTask}
            onClose={() => setSelectedTask(null)}
            onUpdate={handleTaskUpdate}
            onDelete={() => {
              setSelectedTask(null);
              refresh();
            }}
            listId={selectedTask.listId}
            listName={lists.find((l) => l.id === selectedTask.listId)?.name}
            lists={lists}
            onMoveList={async (targetListId) => {
              if (isDemo) {
                const store = getDemoStore();
                const updated = { ...selectedTask, listId: targetListId };
                const newTasks = updateTaskInTree(store.tasks, updated as MockTask);
                saveDemoStore(store.lists, newTasks);
                handleTaskUpdate(updated);
              } else {
                await fetch(`/api/tasks/${selectedTask.id}`, {
                  method: "PATCH",
                  headers: { "Content-Type": "application/json" },
                  body: JSON.stringify({ listId: targetListId }),
                });
                handleTaskUpdate({ ...selectedTask, listId: targetListId });
              }
              refresh();
            }}
            isDemo={isDemo}
            onDemoUpdateTask={handleDemoUpdateTask}
            onDemoDeleteTask={handleDemoDeleteTask}
          />
        </>
      )}

      {/* Global Command Palette (Ctrl+K) */}
      <CommandPalette
        isOpen={cmdPaletteOpen}
        onClose={() => setCmdPaletteOpen(false)}
        tasks={tasks}
        onSelectTask={handleTaskSelect}
      />

      {/* Mobile FAB */}
      <button
        className="fab"
        id="mobile-add-task"
        aria-label="Add task"
        onClick={() => {
          document.dispatchEvent(new CustomEvent("checkflow:addTask"));
        }}
      >
        <svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5">
          <line x1="12" y1="5" x2="12" y2="19" /><line x1="5" y1="12" x2="19" y2="12" />
        </svg>
      </button>
    </div>
  );
}