/**
 * 사용자 설정 스토어 (Zustand + localStorage 지속)
 *
 * 현재는 구조물 시설종별(1종/2종/3종) 표시 필터만 보관한다.
 * VideoPlayer 의 체크박스 UI 가 토글하고, StationBar(재생바)/RoutePanel(좌측 목록)
 * 이 구독해 표시 여부를 결정한다.
 *
 * 지속: zustand persist 미들웨어. localStorage 키 'ghivideo.settings'.
 */

import { create } from 'zustand';
import { persist } from 'zustand/middleware';

/** 필터에서 관리하는 시설종별 집합. 이 외(예 '인상' 등)는 항상 표시. */
export const KNOWN_GRADES = ['1종', '2종', '3종', '기타'] as const;

interface SettingsStore {
  /** 시설종별별 표시 여부. 기본 1종☑ 2종☑ 3종☐ 기타☐ (초기 구동 시 1·2종만 체크). */
  gradeFilter: Record<string, boolean>;
  /** 특정 시설종별 체크 토글. */
  setGradeFilter: (grade: string, checked: boolean) => void;
  /** 화면 POI 겹침제외(겹치면 1개만). true=겹친 것 숨김(기본), false=모든 POI 표시. */
  poiOverlapExclude: boolean;
  setPoiOverlapExclude: (v: boolean) => void;
  /** 좌측 노선 패널(RoutePanel) 표시 여부. '화면표시 옵션' 토글로 제어. 기본 숨김(OFF). */
  showRoutePanel: boolean;
  setShowRoutePanel: (v: boolean) => void;
  /** 측점 진단 HUD(드론 GPS·투영측점) 하단바 표시 여부. 기본 off. */
  showStationDiag: boolean;
  setShowStationDiag: (v: boolean) => void;
  /** 선형(중심선) 영상 오버레이 표시 여부. 기본 표시. (VideoPlayer 바 토글로 제어) */
  showCenterline: boolean;
  setShowCenterline: (v: boolean) => void;
  /** 드론 궤적 영상 오버레이 표시 여부. 기본 표시. (VideoPlayer 바 토글로 제어) */
  showDronePath: boolean;
  setShowDronePath: (v: boolean) => void;
  /** 우측 상단 나침반 타입. 'analog'=눈금 나침반, 'map'=지도(노스업, 현재위치). 기본 map. */
  compassType: 'analog' | 'map';
  setCompassType: (v: 'analog' | 'map') => void;
  /** 지도 나침반 배경. 'street'=OSM 일반, 'sat'=위성(Esri). 기본 street. */
  compassMapStyle: 'street' | 'sat';
  setCompassMapStyle: (v: 'street' | 'sat') => void;
}

const DEFAULT_GRADE_FILTER: Record<string, boolean> = {
  '1종': true,
  '2종': true,
  '3종': false,
  '기타': false,
};

export const useSettingsStore = create<SettingsStore>()(
  persist(
    (set) => ({
      gradeFilter: { ...DEFAULT_GRADE_FILTER },
      setGradeFilter: (grade, checked) =>
        set((s) => ({ gradeFilter: { ...s.gradeFilter, [grade]: checked } })),
      poiOverlapExclude: true,
      setPoiOverlapExclude: (v) => set({ poiOverlapExclude: v }),
      showRoutePanel: false,
      setShowRoutePanel: (v) => set({ showRoutePanel: v }),
      showStationDiag: false,
      setShowStationDiag: (v) => set({ showStationDiag: v }),
      showCenterline: true,
      setShowCenterline: (v) => set({ showCenterline: v }),
      showDronePath: true,
      setShowDronePath: (v) => set({ showDronePath: v }),
      compassType: 'map',
      setCompassType: (v) => set({ compassType: v }),
      compassMapStyle: 'street',
      setCompassMapStyle: (v) => set({ compassMapStyle: v }),
    }),
    {
      name: 'ghivideo.settings',
      // 시작 기본값 변경(좌측패널 OFF + 시설등급 1·2종만) 반영 —
      // 과거 저장본(version 0)은 최초 1회 해당 두 값을 기본으로 강제 재설정한다.
      version: 1,
      migrate: (persisted, version) => {
        const p = (persisted ?? {}) as Partial<SettingsStore>;
        if (version < 1) {
          return { ...p, showRoutePanel: false, gradeFilter: { ...DEFAULT_GRADE_FILTER } } as SettingsStore;
        }
        return p as SettingsStore;
      },
      // 과거 저장본에 누락된 종별 키가 있으면 기본값으로 보충(스키마 진화 대비).
      merge: (persisted, current) => {
        const p = (persisted ?? {}) as Partial<SettingsStore>;
        return {
          ...current,
          ...p,
          gradeFilter: { ...DEFAULT_GRADE_FILTER, ...(p.gradeFilter ?? {}) },
        };
      },
    },
  ),
);

/**
 * 구조물 표시 규칙(공유). 단일 소스로 StationBar/RoutePanel 이 동일 규칙을 쓴다.
 *  - grade 없음(구교 등) 또는 미관리 등급('기타' 등) → 항상 표시
 *  - 1/2/3종 → gradeFilter 가 true 일 때만 표시
 */
export function isGradeVisible(
  grade: string | undefined,
  gradeFilter: Record<string, boolean>,
): boolean {
  if (!grade) return true;
  if (!(KNOWN_GRADES as readonly string[]).includes(grade)) return true;
  return gradeFilter[grade] === true;
}
