"use client";

import React, { useRef, useState, useEffect, useCallback } from "react";
import { flushSync } from "react-dom";
import { X, ChevronDown, RotateCw } from "lucide-react";
import { useTab, TabItem } from "@/contexts/TabContext";
import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuItem,
  DropdownMenuSeparator,
  DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
import { cn } from "@/lib/utils";
import { menuScreenApi } from "@/lib/api/screen";
import { useRouter } from "next/navigation";

const TAB_MIN_WIDTH = 190;
const TAB_MAX_WIDTH = 190;
const TAB_GAP = 2;
const OVERFLOW_BUTTON_WIDTH = 48;

function getTabDisplayName(tab: TabItem): string {
  if (tab.parentMenuName && tab.screenName) {
    return `${tab.parentMenuName} - ${tab.screenName}`;
  }
  return tab.screenName || `화면 ${tab.screenId}`;
}

export function TabBar() {
  const { tabs, activeTabId, switchTab, closeTab, closeOtherTabs, closeAllTabs, closeTabsToTheLeft, closeTabsToTheRight, updateTabOrder, openTab, refreshTab } = useTab();
  const router = useRouter();
  const tabsContainerRef = useRef<HTMLDivElement>(null);
  const [dragOver, setDragOver] = useState(false);
  const [visibleCount, setVisibleCount] = useState(tabs.length);
  const [tabWidth, setTabWidth] = useState(TAB_MAX_WIDTH);
  const [contextMenu, setContextMenu] = useState<{ tabId: string; x: number; y: number } | null>(null);
  const dragStateRef = useRef<{
    tabId: string;
    startX: number;
    startIndex: number;
    currentIndex: number;
    order: string[]; // 드래그 중 논리적 순서 (tabId 배열)
    isDragging: boolean;
  } | null>(null);
  const menuDragInsertRef = useRef<number>(-1);
  const pendingDropRef = useRef<{ timerId: ReturnType<typeof setTimeout>; finalize: () => void } | null>(null);
  const tabsRef = useRef(tabs);
  tabsRef.current = tabs;
  const newDropTabIdRef = useRef<string | null>(null);

  const calculateVisibleTabs = useCallback(() => {
    const container = tabsContainerRef.current;
    if (!container) {
      setVisibleCount(tabs.length);
      return;
    }

    const containerWidth = container.offsetWidth;
    const tabSlotWidth = TAB_MIN_WIDTH + TAB_GAP;

    // 오버플로우 없이 전부 들어가는지 확인
    const totalIfAll = tabs.length * tabSlotWidth;
    if (totalIfAll <= containerWidth) {
      // 전부 표시, 남는 공간을 균등 분배
      setVisibleCount(tabs.length);
      const w = Math.floor(containerWidth / tabs.length) - TAB_GAP;
      setTabWidth(Math.min(TAB_MAX_WIDTH, Math.max(TAB_MIN_WIDTH, w)));
      return;
    }

    // 오버플로우 필요: +N 버튼 공간 확보 후 몇 개 들어가는지 계산
    const availableForTabs = containerWidth - OVERFLOW_BUTTON_WIDTH;
    const count = Math.max(1, Math.floor(availableForTabs / tabSlotWidth));

    setVisibleCount(count);
    const w = Math.floor(availableForTabs / count) - TAB_GAP;
    setTabWidth(Math.min(TAB_MAX_WIDTH, Math.max(TAB_MIN_WIDTH, w)));
  }, [tabs.length]);

  useEffect(() => {
    calculateVisibleTabs();
    const resizeObserver = new ResizeObserver(calculateVisibleTabs);
    if (tabsContainerRef.current) {
      resizeObserver.observe(tabsContainerRef.current);
    }
    return () => resizeObserver.disconnect();
  }, [calculateVisibleTabs]);

  useEffect(() => {
    const handleClick = () => setContextMenu(null);
    if (contextMenu) {
      document.addEventListener("click", handleClick);
      return () => document.removeEventListener("click", handleClick);
    }
  }, [contextMenu]);

  if (tabs.length === 0) {
    return (
      <div className="relative flex h-9 min-w-0 items-end bg-slate-50 px-1 overflow-hidden shadow-[inset_0_-1px_0_0_rgb(226,232,240)]" />
    );
  }

  const visibleTabs = tabs.slice(0, visibleCount);
  const overflowTabs = tabs.slice(visibleCount);
  const hasOverflow = overflowTabs.length > 0;

  // 활성 탭이 오버플로우에 있는 경우, 보이는 탭의 마지막을 교체
  const activeInOverflow = overflowTabs.find(t => t.id === activeTabId);
  let displayVisibleTabs = [...visibleTabs];
  let displayOverflowTabs = [...overflowTabs];

  if (activeInOverflow && visibleTabs.length > 0) {
    const lastVisible = displayVisibleTabs[displayVisibleTabs.length - 1];
    displayVisibleTabs[displayVisibleTabs.length - 1] = activeInOverflow;
    displayOverflowTabs = displayOverflowTabs.filter(t => t.id !== activeInOverflow.id);
    displayOverflowTabs.unshift(lastVisible);
  }

  const handleContextMenu = (e: React.MouseEvent, tabId: string) => {
    e.preventDefault();
    setContextMenu({ tabId, x: e.clientX, y: e.clientY });
  };

  const applyDragTransforms = (order: string[], dragId: string, dragDx: number) => {
    const container = tabsContainerRef.current;
    if (!container) return;
    const slotWidth = tabWidth + TAB_GAP;
    const originalOrder = tabsRef.current.map(t => t.id);

    order.forEach((id, newIdx) => {
      const el = container.querySelector(`[data-tab-id="${id}"]`) as HTMLElement | null;
      if (!el) return;
      const origIdx = originalOrder.indexOf(id);
      if (origIdx === -1) return;

      if (id === dragId) {
        el.style.transform = `translateX(${dragDx}px)`;
        el.style.zIndex = "50";
        el.style.opacity = "0.85";
      } else {
        const offset = (newIdx - origIdx) * slotWidth;
        el.style.transform = offset !== 0 ? `translateX(${offset}px)` : "";
        el.style.zIndex = "";
        el.style.opacity = "";
      }
      el.style.transition = "none";
    });
  };

  const clearAllTransforms = () => {
    const container = tabsContainerRef.current;
    if (!container) return;
    container.querySelectorAll("[data-tab-id]").forEach((el) => {
      const h = el as HTMLElement;
      h.style.transform = "";
      h.style.zIndex = "";
      h.style.opacity = "";
      h.style.transition = "";
    });
  };

  const handleTabMouseDown = (e: React.MouseEvent, tabId: string) => {
    if (e.button === 1) {
      e.preventDefault();
      closeTab(tabId);
      return;
    }
    if (e.button !== 0) return;
    if ((e.target as HTMLElement).closest("button")) return;

    // 이전 드롭 애니메이션이 진행 중이면 즉시 완료
    if (pendingDropRef.current) {
      clearTimeout(pendingDropRef.current.timerId);
      pendingDropRef.current.finalize();
      pendingDropRef.current = null;
    }

    const container = tabsContainerRef.current;
    if (!container) return;

    // finalize() 후 flushSync로 상태가 갱신되었으므로 최신 tabs 사용
    const currentTabs = tabsRef.current;
    const startIndex = currentTabs.findIndex(t => t.id === tabId);
    const startX = e.clientX;
    const slotWidth = tabWidth + TAB_GAP;
    const order = currentTabs.map(t => t.id);

    dragStateRef.current = {
      tabId,
      startX,
      startIndex,
      currentIndex: startIndex,
      order,
      isDragging: false,
    };

    const handleMouseMove = (moveEvent: MouseEvent) => {
      const state = dragStateRef.current;
      if (!state) return;

      const dx = moveEvent.clientX - state.startX;
      if (!state.isDragging && Math.abs(dx) > 4) {
        state.isDragging = true;
      }
      if (!state.isDragging) return;

      // 마우스 위치로 목표 슬롯 계산
      const containerLeft = container.getBoundingClientRect().left + 4;
      const mouseRelX = moveEvent.clientX - containerLeft;
      const targetSlot = Math.max(0, Math.min(visibleCount - 1, Math.floor(mouseRelX / slotWidth)));

      // 순서 배열에서 직접 이동 (React 상태 안 건드림)
      if (targetSlot !== state.currentIndex) {
        const [moved] = state.order.splice(state.currentIndex, 1);
        state.order.splice(targetSlot, 0, moved);
        state.currentIndex = targetSlot;
      }

      // 드래그 탭의 시각적 위치: 원래 슬롯 기준 마우스 이동량
      const visualDx = dx;
      applyDragTransforms(state.order, state.tabId, visualDx);
    };

    const handleMouseUp = () => {
      const state = dragStateRef.current;
      dragStateRef.current = null;
      document.removeEventListener("mousemove", handleMouseMove);
      document.removeEventListener("mouseup", handleMouseUp);

      if (state && state.isDragging && state.currentIndex !== state.startIndex) {
        const dragEl = container.querySelector(`[data-tab-id="${state.tabId}"]`) as HTMLElement | null;
        const targetOffset = (state.currentIndex - state.startIndex) * slotWidth;
        const newOrder = [...state.order];

        if (dragEl) {
          dragEl.style.transition = "transform 150ms ease, opacity 150ms ease";
          dragEl.style.transform = `translateX(${targetOffset}px)`;
          dragEl.style.opacity = "1";
          dragEl.style.zIndex = "50";
        }

        const finalize = () => {
          clearAllTransforms();
          flushSync(() => updateTabOrder(newOrder));
          pendingDropRef.current = null;
        };
        const timerId = setTimeout(finalize, 150);
        pendingDropRef.current = { timerId, finalize };
      } else if (state && state.isDragging) {
        const dragEl = container.querySelector(`[data-tab-id="${state.tabId}"]`) as HTMLElement | null;
        if (dragEl) {
          dragEl.style.transition = "transform 150ms ease, opacity 150ms ease";
          dragEl.style.transform = "translateX(0)";
          dragEl.style.opacity = "1";
        }

        const finalize = () => {
          clearAllTransforms();
          pendingDropRef.current = null;
        };
        const timerId = setTimeout(finalize, 150);
        pendingDropRef.current = { timerId, finalize };
      } else {
        clearAllTransforms();
        if (state) switchTab(tabId);
      }
    };

    document.addEventListener("mousemove", handleMouseMove);
    document.addEventListener("mouseup", handleMouseUp);
  };

  const applyMenuDragGap = (insertIdx: number) => {
    const container = tabsContainerRef.current;
    if (!container) return;
    const slotWidth = tabWidth + TAB_GAP;

    displayVisibleTabs.forEach((tab, i) => {
      const el = container.querySelector(`[data-tab-id="${tab.id}"]`) as HTMLElement | null;
      if (!el) return;
      if (i >= insertIdx) {
        el.style.transform = `translateX(${slotWidth}px)`;
        el.style.transition = "transform 150ms ease";
      } else {
        el.style.transform = "";
        el.style.transition = "transform 150ms ease";
      }
    });
  };

  const clearMenuDragGap = () => {
    const container = tabsContainerRef.current;
    if (!container) return;
    container.querySelectorAll("[data-tab-id]").forEach((el) => {
      const h = el as HTMLElement;
      h.style.transform = "";
      h.style.transition = "";
    });
    menuDragInsertRef.current = -1;
  };

  const handleMenuDragOver = (e: React.DragEvent) => {
    if (e.dataTransfer.types.includes("application/tab-menu")) {
      e.preventDefault();
      e.dataTransfer.dropEffect = "copy";
      if (!dragOver) setDragOver(true);

      const container = tabsContainerRef.current;
      if (container) {
        const containerLeft = container.getBoundingClientRect().left + 4;
        const mouseRelX = e.clientX - containerLeft;
        const slotWidth = tabWidth + TAB_GAP;
        const insertIdx = Math.max(0, Math.min(displayVisibleTabs.length, Math.round(mouseRelX / slotWidth)));

        if (insertIdx !== menuDragInsertRef.current) {
          menuDragInsertRef.current = insertIdx;
          applyMenuDragGap(insertIdx);
        }
      }
    }
  };

  const handleMenuDragLeave = (e: React.DragEvent) => {
    const container = tabsContainerRef.current;
    if (container && !container.contains(e.relatedTarget as Node)) {
      setDragOver(false);
      clearMenuDragGap();
    }
  };

  const handleMenuDrop = async (e: React.DragEvent) => {
    e.preventDefault();
    setDragOver(false);

    const insertIndex = menuDragInsertRef.current >= 0
      ? menuDragInsertRef.current
      : undefined;

    clearMenuDragGap();

    const raw = e.dataTransfer.getData("application/tab-menu");
    if (!raw) return;

    try {
      const data = JSON.parse(raw);
      const { menuObjid, menuName, parentMenuName } = data;

      const assignedScreens = await menuScreenApi.getScreensByMenu(menuObjid);
      if (assignedScreens.length > 0) {
        const firstScreen = assignedScreens[0];

        const expectedTabId = `tab-${firstScreen.screenId}-${menuObjid || "default"}`;
        const alreadyOpen = tabs.some(t => t.id === expectedTabId);

        if (!alreadyOpen) {
          newDropTabIdRef.current = expectedTabId;
        }

        openTab({
          screenId: firstScreen.screenId,
          menuObjid,
          screenName: menuName,
          menuName: menuName,
          parentMenuName: parentMenuName,
        }, insertIndex);

        const urlParams = new URLSearchParams();
        urlParams.set("menuObjid", menuObjid.toString());
        router.replace(`/screens/${firstScreen.screenId}?${urlParams.toString()}`);

        if (!alreadyOpen) {
          requestAnimationFrame(() => {
            const container = tabsContainerRef.current;
            if (!container) return;
            const newEl = container.querySelector(`[data-tab-id="${expectedTabId}"]`) as HTMLElement | null;
            if (newEl) {
              newEl.style.transition = "none";
              newEl.style.transform = "scale(0.85)";
              newEl.style.opacity = "0";
              requestAnimationFrame(() => {
                newEl.style.transition = "transform 150ms ease, opacity 150ms ease";
                newEl.style.transform = "scale(1)";
                newEl.style.opacity = "1";
                setTimeout(() => {
                  newEl.style.transition = "";
                  newEl.style.transform = "";
                  newEl.style.opacity = "";
                  newDropTabIdRef.current = null;
                }, 160);
              });
            }
          });
        }
      }
    } catch (error) {
      console.warn("드래그 드롭 탭 생성 실패:", error);
    }
  };

  return (
    <div
      className={cn(
        "relative flex h-9 min-w-0 items-end bg-slate-50 px-1 overflow-hidden shadow-[inset_0_-1px_0_0_rgb(226,232,240)]",
        dragOver && "shadow-[inset_0_-2px_0_0_rgb(59,130,246)]",
      )}
      ref={tabsContainerRef}
      onDragOver={handleMenuDragOver}
      onDragLeave={handleMenuDragLeave}
      onDrop={handleMenuDrop}
    >
      {/* 탭 + 오버플로우 버튼이 나란히 배치 */}
      <div className="flex min-w-0 items-end">
        {displayVisibleTabs.map((tab) => {
          const isActive = tab.id === activeTabId;
          const displayName = getTabDisplayName(tab);

          return (
            <div
              key={tab.id}
              data-tab-id={tab.id}
              style={{ width: `${tabWidth}px` }}
              className={cn(
                "group relative mr-0.5 flex shrink-0 cursor-pointer items-center gap-1 rounded-t-lg border px-3 text-xs font-medium select-none transition-colors",
                isActive
                  ? "z-10 h-[33px] border-slate-200 border-b-0 bg-white text-slate-900"
                  : "h-8 border-transparent text-slate-500 hover:bg-slate-100 hover:text-slate-700",
              )}
              onMouseDown={(e) => handleTabMouseDown(e, tab.id)}
              onDragStart={(e) => e.preventDefault()}
              onContextMenu={(e) => handleContextMenu(e, tab.id)}
              title={displayName}
            >
              <span className="min-w-0 flex-1 truncate">{displayName}</span>
              {isActive && (
                <button
                  className="flex h-4 w-4 shrink-0 items-center justify-center rounded-sm text-slate-400 transition-colors hover:bg-slate-200 hover:text-slate-700"
                  onClick={(e) => {
                    e.stopPropagation();
                    refreshTab(tab.id);
                  }}
                  title="새로고침"
                >
                  <RotateCw className="h-2.5 w-2.5" />
                </button>
              )}
              <button
                className={cn(
                  "flex h-4 w-4 shrink-0 items-center justify-center rounded-sm transition-colors",
                  isActive
                    ? "text-slate-400 hover:bg-slate-200 hover:text-slate-700"
                    : "text-transparent group-hover:text-slate-400 group-hover:hover:bg-slate-200 group-hover:hover:text-slate-700",
                )}
                onClick={(e) => {
                  e.stopPropagation();
                  closeTab(tab.id);
                }}
              >
                <X className="h-3 w-3" />
              </button>
            </div>
          );
        })}

        {/* 오버플로우 드롭다운 - 마지막 탭 바로 옆 */}
        {hasOverflow && (
          <DropdownMenu>
            <DropdownMenuTrigger asChild>
              <button
                className="mb-0.5 flex h-7 shrink-0 items-center justify-center gap-0.5 rounded-md px-2 text-xs font-medium text-slate-500 transition-colors hover:bg-slate-200 hover:text-slate-700"
                title={`외 ${displayOverflowTabs.length}개 탭`}
              >
                <span className="text-[10px]">+{displayOverflowTabs.length}</span>
                <ChevronDown className="h-3 w-3" />
              </button>
            </DropdownMenuTrigger>
            <DropdownMenuContent align="start" className="max-h-[400px] w-[280px] overflow-y-auto">
              {displayOverflowTabs.map((tab) => {
                const isActive = tab.id === activeTabId;

                return (
                  <DropdownMenuItem
                    key={tab.id}
                    className={cn(
                      "flex cursor-pointer items-center justify-between gap-2",
                      isActive && "bg-slate-100 font-semibold",
                    )}
                    onClick={() => switchTab(tab.id)}
                  >
                    <div className="flex min-w-0 flex-1 flex-col">
                      {tab.parentMenuName && (
                        <span className="text-[10px] text-slate-400">{tab.parentMenuName}</span>
                      )}
                      <span className="truncate text-xs">{tab.screenName || `화면 ${tab.screenId}`}</span>
                    </div>
                    <button
                      className="flex h-4 w-4 shrink-0 items-center justify-center rounded-sm text-slate-400 hover:bg-slate-200 hover:text-slate-700"
                      onClick={(e) => {
                        e.stopPropagation();
                        closeTab(tab.id);
                      }}
                    >
                      <X className="h-3 w-3" />
                    </button>
                  </DropdownMenuItem>
                );
              })}
              <DropdownMenuSeparator />
              <DropdownMenuItem
                className="cursor-pointer text-xs text-slate-500"
                onClick={closeAllTabs}
              >
                모든 탭 닫기
              </DropdownMenuItem>
            </DropdownMenuContent>
          </DropdownMenu>
        )}
      </div>

      {/* 우클릭 컨텍스트 메뉴 */}
      {contextMenu && (
        <div
          className="fixed z-50 min-w-[160px] rounded-md border border-slate-200 bg-white py-1 shadow-lg"
          style={{ left: contextMenu.x, top: contextMenu.y }}
        >
          <button
            className="flex w-full items-center px-3 py-1.5 text-xs text-slate-700 hover:bg-slate-100"
            onClick={() => {
              refreshTab(contextMenu.tabId);
              setContextMenu(null);
            }}
          >
            새로고침
          </button>
          <div className="my-1 border-t border-slate-200" />
          <button
            className="flex w-full items-center px-3 py-1.5 text-xs text-slate-700 hover:bg-slate-100"
            onClick={() => {
              closeTab(contextMenu.tabId);
              setContextMenu(null);
            }}
          >
            탭 닫기
          </button>
          <button
            className="flex w-full items-center px-3 py-1.5 text-xs text-slate-700 hover:bg-slate-100"
            onClick={() => {
              closeOtherTabs(contextMenu.tabId);
              setContextMenu(null);
            }}
          >
            다른 탭 모두 닫기
          </button>
          <button
            className="flex w-full items-center px-3 py-1.5 text-xs text-slate-700 hover:bg-slate-100"
            onClick={() => {
              closeTabsToTheLeft(contextMenu.tabId);
              setContextMenu(null);
            }}
          >
            왼쪽 탭 모두 닫기
          </button>
          <button
            className="flex w-full items-center px-3 py-1.5 text-xs text-slate-700 hover:bg-slate-100"
            onClick={() => {
              closeTabsToTheRight(contextMenu.tabId);
              setContextMenu(null);
            }}
          >
            오른쪽 탭 모두 닫기
          </button>
          <div className="my-1 border-t border-slate-200" />
          <button
            className="flex w-full items-center px-3 py-1.5 text-xs text-red-600 hover:bg-red-50"
            onClick={() => {
              closeAllTabs();
              setContextMenu(null);
            }}
          >
            모든 탭 닫기
          </button>
        </div>
      )}
    </div>
  );
}
