"use client";

import React, { useRef, useEffect, useCallback } from "react";
import { useTabStore, selectTabs, selectActiveTabId } from "@/stores/tabStore";
import { ScreenViewPageWrapper } from "@/app/(main)/screens/[screenId]/page";
import { AdminPageRenderer } from "./AdminPageRenderer";
import { EmptyDashboard } from "./EmptyDashboard";
import { TabIdProvider } from "@/contexts/TabIdContext";
import { registerModalPortal } from "@/lib/modalPortalRef";
import ScreenModal from "@/components/common/ScreenModal";
import {
  saveTabCacheImmediate,
  loadTabCache,
  captureAllScrollPositions,
  restoreAllScrollPositions,
  getElementPath,
  captureFormState,
  restoreFormState,
  clearTabCache,
} from "@/lib/tabStateCache";

// 페이지 로드(F5 새로고침) 감지용 모듈 레벨 플래그.
// 전체 페이지 로드 시 모듈이 재실행되어 false로 리셋된다.
// SPA 내비게이션에서는 모듈이 유지되므로 true로 남는다.
let hasHandledPageLoad = false;

export function TabContent() {
  const tabs = useTabStore(selectTabs);
  const activeTabId = useTabStore(selectActiveTabId);
  const refreshKeys = useTabStore((s) => s.refreshKeys);

  // 한 번이라도 활성화된 탭만 마운트 (지연 마운트)
  const mountedTabIdsRef = useRef<Set<string>>(new Set());

  // 각 탭의 스크롤 컨테이너 ref
  const scrollRefsMap = useRef<Map<string, HTMLDivElement | null>>(new Map());

  // 이전 활성 탭 ID 추적
  const prevActiveTabIdRef = useRef<string | null>(null);

  // 활성 탭의 스크롤 위치를 실시간 추적 (display:none 전에 캡처하기 위함)
  // Map<tabId, Map<elementPath, {top, left}>> - 탭 내 여러 스크롤 영역을 각각 추적
  const lastScrollMapRef = useRef<Map<string, Map<string, { top: number; left: number }>>>(new Map());
  // 요소 → 경로 캐시 (매 스크롤 이벤트마다 경로를 재계산하지 않기 위함)
  const pathCacheRef = useRef<WeakMap<HTMLElement, string | null>>(new WeakMap());

  // 페이지 로드(F5) 시 활성 탭 캐시만 삭제 → fresh API 호출 유도
  // 비활성 탭 캐시는 유지하여 탭 전환 시 복원
  if (!hasHandledPageLoad && activeTabId) {
    hasHandledPageLoad = true;
    clearTabCache(activeTabId);
  }

  if (activeTabId) {
    mountedTabIdsRef.current.add(activeTabId);
  }

  // 활성 탭의 scroll 이벤트를 감지하여 요소별 위치를 실시간 저장
  useEffect(() => {
    if (!activeTabId) return;

    const container = scrollRefsMap.current.get(activeTabId);
    if (!container) return;

    const handleScroll = (e: Event) => {
      const target = e.target as HTMLElement;

      let path = pathCacheRef.current.get(target);
      if (path === undefined) {
        path = getElementPath(target, container);
        pathCacheRef.current.set(target, path);
      }
      if (path === null) return;

      let tabMap = lastScrollMapRef.current.get(activeTabId);
      if (!tabMap) {
        tabMap = new Map();
        lastScrollMapRef.current.set(activeTabId, tabMap);
      }

      if (target.scrollTop > 0 || target.scrollLeft > 0) {
        tabMap.set(path, { top: target.scrollTop, left: target.scrollLeft });
      } else {
        tabMap.delete(path);
      }
    };

    container.addEventListener("scroll", handleScroll, true);
    return () => container.removeEventListener("scroll", handleScroll, true);
  }, [activeTabId]);

  // 복원 관련 cleanup ref
  const scrollRestoreCleanupRef = useRef<(() => void) | null>(null);
  const formRestoreCleanupRef = useRef<(() => void) | null>(null);

  // 탭 전환 시: 이전 탭 상태 캐싱, 새 탭 상태 복원
  useEffect(() => {
    // 이전 복원 작업 취소
    if (scrollRestoreCleanupRef.current) {
      scrollRestoreCleanupRef.current();
      scrollRestoreCleanupRef.current = null;
    }
    if (formRestoreCleanupRef.current) {
      formRestoreCleanupRef.current();
      formRestoreCleanupRef.current = null;
    }

    const prevId = prevActiveTabIdRef.current;

    // 이전 활성 탭의 스크롤 + 폼 상태 저장
    // 키를 항상 포함하여 이전 캐시의 오래된 값이 병합으로 살아남지 않도록 함
    if (prevId && prevId !== activeTabId) {
      const tabMap = lastScrollMapRef.current.get(prevId);
      const scrollPositions =
        tabMap && tabMap.size > 0
          ? Array.from(tabMap.entries()).map(([path, pos]) => ({ path, ...pos }))
          : undefined;
      const prevEl = scrollRefsMap.current.get(prevId);
      const formFields = captureFormState(prevEl ?? null);
      saveTabCacheImmediate(prevId, {
        scrollPositions,
        domFormFields: formFields ?? undefined,
      });
    }

    // 새 활성 탭의 스크롤 + 폼 상태 복원
    if (activeTabId) {
      const cache = loadTabCache(activeTabId);
      if (cache) {
        const el = scrollRefsMap.current.get(activeTabId);
        if (cache.scrollPositions) {
          const cleanup = restoreAllScrollPositions(el ?? null, cache.scrollPositions);
          if (cleanup) scrollRestoreCleanupRef.current = cleanup;
        }
        if (cache.domFormFields) {
          const cleanup = restoreFormState(el ?? null, cache.domFormFields ?? null);
          if (cleanup) formRestoreCleanupRef.current = cleanup;
        }
      }
    }

    prevActiveTabIdRef.current = activeTabId;
  }, [activeTabId]);

  // F5 새로고침 직전에 활성 탭의 스크롤/폼 상태를 저장
  useEffect(() => {
    const handleBeforeUnload = () => {
      const currentActiveId = prevActiveTabIdRef.current;
      if (!currentActiveId) return;

      const el = scrollRefsMap.current.get(currentActiveId);
      // 활성 탭은 display:block이므로 DOM에서 직접 캡처 (가장 정확)
      const scrollPositions = captureAllScrollPositions(el ?? null);
      // DOM 캡처 실패 시 실시간 추적 데이터 fallback
      const tabMap = lastScrollMapRef.current.get(currentActiveId);
      const trackedPositions =
        !scrollPositions && tabMap && tabMap.size > 0
          ? Array.from(tabMap.entries()).map(([path, pos]) => ({ path, ...pos }))
          : undefined;

      const finalPositions = scrollPositions || trackedPositions;
      const formFields = captureFormState(el ?? null);
      saveTabCacheImmediate(currentActiveId, {
        scrollPositions: finalPositions,
        domFormFields: formFields ?? undefined,
      });
    };

    window.addEventListener("beforeunload", handleBeforeUnload);
    return () => {
      window.removeEventListener("beforeunload", handleBeforeUnload);
      if (scrollRestoreCleanupRef.current) scrollRestoreCleanupRef.current();
      if (formRestoreCleanupRef.current) formRestoreCleanupRef.current();
    };
  }, []);

  // 탭 닫기 시 캐시 정리 (tabs 배열 변화 감지)
  useEffect(() => {
    const currentTabIds = new Set(tabs.map((t) => t.id));
    const mountedIds = mountedTabIdsRef.current;

    mountedIds.forEach((id) => {
      if (!currentTabIds.has(id)) {
        clearTabCache(id);
        scrollRefsMap.current.delete(id);
        mountedIds.delete(id);
      }
    });
  }, [tabs]);

  const setScrollRef = useCallback((tabId: string, el: HTMLDivElement | null) => {
    scrollRefsMap.current.set(tabId, el);
  }, []);

  // 포탈 컨테이너 ref callback: 전역 레퍼런스에 등록
  const portalRefCallback = useCallback((el: HTMLDivElement | null) => {
    registerModalPortal(el);
  }, []);

  if (tabs.length === 0) {
    return <EmptyDashboard />;
  }

  const tabLookup = new Map(tabs.map((t) => [t.id, t]));
  const stableIds = Array.from(mountedTabIdsRef.current);

  return (
    <div ref={portalRefCallback} className="relative min-h-0 flex-1 overflow-hidden">
      {stableIds.map((tabId) => {
        const tab = tabLookup.get(tabId);
        if (!tab) return null;

        const isActive = tab.id === activeTabId;
        const refreshKey = refreshKeys[tab.id] || 0;

        return (
          <div
            key={tab.id}
            ref={(el) => setScrollRef(tab.id, el)}
            className="absolute inset-0 overflow-hidden"
            style={{ display: isActive ? "block" : "none" }}
          >
            <TabIdProvider value={tab.id}>
              <TabPageRenderer tab={tab} refreshKey={refreshKey} />
              <ScreenModal key={`modal-${tab.id}-${refreshKey}`} />
            </TabIdProvider>
          </div>
        );
      })}
    </div>
  );
}

function TabPageRenderer({
  tab,
  refreshKey,
}: {
  tab: { id: string; type: string; screenId?: number; menuObjid?: number; adminUrl?: string };
  refreshKey: number;
}) {
  console.log("[TabPageRenderer] 탭 렌더링:", {
    tabId: tab.id,
    type: tab.type,
    screenId: tab.screenId,
    adminUrl: tab.adminUrl,
    menuObjid: tab.menuObjid,
  });

  if (tab.type === "screen" && tab.screenId != null) {
    return (
      <ScreenViewPageWrapper
        key={`${tab.id}-${refreshKey}`}
        screenIdProp={tab.screenId}
        menuObjidProp={tab.menuObjid}
      />
    );
  }

  if (tab.type === "admin" && tab.adminUrl) {
    return (
      <div key={`${tab.id}-${refreshKey}`} className="h-full">
        <AdminPageRenderer url={tab.adminUrl} />
      </div>
    );
  }

  console.warn("[TabPageRenderer] 렌더링 불가 - 매칭 조건 없음:", tab);
  return null;
}
