/*
 * MDI(다중 문서 인터페이스) 탭 상태 (zustand) — design.md §2.7 MDI 셸.
 *
 * W7 범위(셸 레이어 라우팅 래핑 = "탭 = 라우트 북마크"):
 * 라우트 구조는 App.tsx 가 소유(불변). 이 스토어는 열린 문서 탭의 목록·활성 경로만 관리하며
 * 실제 화면 전환은 react-router 이 담당한다. 비활성 탭의 DOM 상태 보존(display:none DocumentHost)은
 * 후속 웨이브 과제로, 본 웨이브는 순증 레이어(탭 북마크 + 현재 라우트 동기화)만 구현한다.
 *
 * 지속: sessionStorage(새로고침 유지, 브라우저 종료 시 소멸). 직렬화 대상은 {path,label} 목록·활성 path.
 * 패턴: themeStore(모듈 로드 시 초기값 복원, set 시 즉시 저장).
 */
import { create } from 'zustand';

export interface MdiTab {
  /** 문서 라우트(딥링크) — 문서키 겸 dedup 기준. */
  path: string;
  /** 탭에 표시할 화면명(라벨 매핑 테이블 해소값). */
  label: string;
}

/** 동시 열림 상한 — 초과 시 가장 오래된 비활성 탭을 닫는다. */
export const MAX_TABS = 10;

const STORAGE_KEY = 'kx-mdi';

interface Persisted {
  tabs: MdiTab[];
  activePath: string | null;
}

function readStored(): Persisted {
  if (typeof sessionStorage === 'undefined') return { tabs: [], activePath: null };
  try {
    const raw = sessionStorage.getItem(STORAGE_KEY);
    if (!raw) return { tabs: [], activePath: null };
    const parsed = JSON.parse(raw) as Partial<Persisted>;
    const tabs = Array.isArray(parsed.tabs)
      ? parsed.tabs.filter(
          (t): t is MdiTab =>
            !!t && typeof t.path === 'string' && typeof t.label === 'string',
        )
      : [];
    const activePath =
      typeof parsed.activePath === 'string' && tabs.some((t) => t.path === parsed.activePath)
        ? parsed.activePath
        : (tabs[tabs.length - 1]?.path ?? null);
    return { tabs, activePath };
  } catch {
    return { tabs: [], activePath: null };
  }
}

function persist(state: Persisted) {
  if (typeof sessionStorage === 'undefined') return;
  try {
    sessionStorage.setItem(
      STORAGE_KEY,
      JSON.stringify({ tabs: state.tabs, activePath: state.activePath }),
    );
  } catch {
    /* 저장 실패(쿼터·프라이빗 모드)는 무시 — 세션 지속은 best-effort. */
  }
}

interface MdiState {
  tabs: MdiTab[];
  activePath: string | null;

  /**
   * 문서 탭 열기/활성 전환 — 현재 라우트 동기화의 진입점.
   * 이미 열린 경로면 새로 만들지 않고 활성만 전환(중복 방지, §2.7-2).
   * 라벨이 갱신되면 반영한다(예: 딥링크로 먼저 열린 뒤 매핑 해소).
   * 상한 초과 시 가장 오래된 비활성 탭을 닫는다.
   */
  openTab: (path: string, label: string) => void;

  /** 탭 활성 전환(경로가 목록에 있을 때만). */
  activateTab: (path: string) => void;

  /**
   * 탭 닫기. 활성 탭을 닫으면 오른쪽(없으면 왼쪽) 인접 탭을 활성으로 계산한다.
   * @returns 닫은 뒤 이동해야 할 활성 경로(없으면 null) — 호출부가 navigate 담당.
   */
  closeTab: (path: string) => string | null;

  /** 전 탭 닫기(모두 닫기). @returns 이동할 기본 경로('/home') — 호출부가 navigate 담당. */
  closeAll: () => string;
}

const initial = readStored();

export const useMdiStore = create<MdiState>((set, get) => ({
  tabs: initial.tabs,
  activePath: initial.activePath,

  openTab: (path, label) => {
    const { tabs } = get();
    const existing = tabs.find((t) => t.path === path);
    let next: MdiTab[];
    if (existing) {
      // 라벨만 갱신(위치 유지) — 중복 생성 금지.
      next = existing.label === label
        ? tabs
        : tabs.map((t) => (t.path === path ? { ...t, label } : t));
    } else {
      next = [...tabs, { path, label }];
      // 상한 초과 → 가장 오래된 비활성 탭 제거(활성 대상·방금 연 탭 제외).
      if (next.length > MAX_TABS) {
        const victim = next.find((t) => t.path !== path);
        if (victim) next = next.filter((t) => t.path !== victim.path);
      }
    }
    const state = { tabs: next, activePath: path };
    persist(state);
    set(state);
  },

  activateTab: (path) => {
    const { tabs } = get();
    if (!tabs.some((t) => t.path === path)) return;
    const state = { tabs, activePath: path };
    persist(state);
    set({ activePath: path });
  },

  closeTab: (path) => {
    const { tabs, activePath } = get();
    const idx = tabs.findIndex((t) => t.path === path);
    if (idx === -1) return activePath;
    const next = tabs.filter((t) => t.path !== path);

    let nextActive = activePath;
    if (activePath === path) {
      // 오른쪽 우선, 없으면 왼쪽 인접.
      const neighbor = tabs[idx + 1] ?? tabs[idx - 1] ?? null;
      nextActive = neighbor ? neighbor.path : null;
    }
    const state = { tabs: next, activePath: nextActive };
    persist(state);
    set(state);
    return nextActive;
  },

  closeAll: () => {
    const state = { tabs: [], activePath: null };
    persist(state);
    set(state);
    return '/home';
  },
}));
