import { useState, useCallback } from 'react';
import { useTranslation } from 'react-i18next';
import { useLocalStorageSet } from '../../hooks/useLocalStorage';
import { FontScalePanel } from './FontScalePanel';

// Aircraft category colors (matches AircraftLayer military fixed colors)
const AC_CAT_COLORS: Record<string, string> = {
  fighter: '#ff4444',
  military: '#ff6600',
  surveillance: '#ffcc00',
  tanker: '#00ccff',
  cargo: '#a78bfa',
  civilian: '#FFD700',
  unknown: '#7CFC00',
};

// Altitude color legend (matches AircraftLayer gradient)
const ALT_LEGEND: [string, string][] = [
  ['Ground', '#555555'],
  ['< 2,000ft', '#00c000'],
  ['2,000ft', '#55EC55'],
  ['4,000ft', '#7CFC00'],
  ['6,000ft', '#BFFF00'],
  ['10,000ft', '#FFFF00'],
  ['20,000ft', '#FFD700'],
  ['30,000ft', '#FF8C00'],
  ['40,000ft', '#FF4500'],
  ['50,000ft+', '#BA55D3'],
];

// Military color legend
const MIL_LEGEND: [string, string][] = [
  ['Fighter', '#ff4444'],
  ['Military', '#ff6600'],
  ['ISR / Surveillance', '#ffcc00'],
  ['Tanker', '#00ccff'],
];

// Ship MT category color (matches ShipLayer MT_TYPE_COLORS)
const MT_CAT_COLORS: Record<string, string> = {
  cargo: 'var(--kcg-ship-cargo)',
  tanker: 'var(--kcg-ship-tanker)',
  passenger: 'var(--kcg-ship-passenger)',
  fishing: 'var(--kcg-ship-fishing)',
  fishing_gear: '#f97316',
  military: 'var(--kcg-ship-military)',
  tug_special: 'var(--kcg-ship-tug)',
  high_speed: 'var(--kcg-ship-highspeed)',
  pleasure: 'var(--kcg-ship-pleasure)',
  other: 'var(--kcg-ship-other)',
  unspecified: 'var(--kcg-ship-unknown)',
  unknown: 'var(--kcg-ship-unknown)',
};

// Ship type color legend (MarineTraffic style)
const SHIP_TYPE_LEGEND: [string, string][] = [
  ['cargo', 'var(--kcg-ship-cargo)'],
  ['tanker', 'var(--kcg-ship-tanker)'],
  ['passenger', 'var(--kcg-ship-passenger)'],
  ['fishing', 'var(--kcg-ship-fishing)'],
  ['fishing_gear', '#f97316'],
  ['pleasure', 'var(--kcg-ship-pleasure)'],
  ['military', 'var(--kcg-ship-military)'],
  ['tug_special', 'var(--kcg-ship-tug)'],
  ['other', 'var(--kcg-ship-other)'],
  ['unspecified', 'var(--kcg-ship-unknown)'],
];

const AC_CATEGORIES = ['fighter', 'military', 'surveillance', 'tanker', 'cargo', 'civilian', 'unknown'] as const;
const MT_CATEGORIES = ['cargo', 'tanker', 'passenger', 'fishing', 'fishing_gear', 'military', 'tug_special', 'high_speed', 'pleasure', 'other', 'unspecified'] as const;

// Nationality categories for Korea tab
const NAT_CATEGORIES = ['KR', 'CN', 'KP', 'JP', 'unclassified'] as const;

// Fishing vessel nationality categories
const FISHING_NAT_CATEGORIES = ['CN', 'KR', 'JP', 'other'] as const;
const FISHING_NAT_LABELS: Record<string, string> = {
  CN: '🇨🇳 중국어선',
  KR: '🇰🇷 한국어선',
  JP: '🇯🇵 일본어선',
  other: '🏳️ 기타어선',
};
const FISHING_NAT_COLORS: Record<string, string> = {
  CN: '#ef4444',
  KR: '#3b82f6',
  JP: '#f472b6',
  other: '#6b7280',
};
const NAT_LABELS: Record<string, string> = {
  KR: '🇰🇷 한국',
  CN: '🇨🇳 중국',
  KP: '🇰🇵 북한',
  JP: '🇯🇵 일본',
  unclassified: '🏳️ 미분류',
};
const NAT_COLORS: Record<string, string> = {
  KR: '#3b82f6',
  CN: '#ef4444',
  KP: '#f97316',
  JP: '#f472b6',
  unclassified: '#6b7280',
};

// ── New tree interface ────────────────────────────────

export interface LayerTreeNode {
  key: string;
  label: string;
  color: string;
  count?: number;
  children?: LayerTreeNode[];
  specialRenderer?: 'shipCategories' | 'aircraftCategories' | 'nationalityCategories';
}

// ── Legacy interfaces (kept for backward compat) ─────

interface ExtraLayer {
  key: string;
  label: string;
  color: string;
  count?: number;
  group?: string;
}

const GROUP_META: Record<string, { label: string; color: string; superGroup?: string }> = {
  '항공망':         { label: '항공망',         color: '#22d3ee' },
  '해양안전':       { label: '해양안전',       color: '#3b82f6' },
  '국가기관망':     { label: '국가기관망',     color: '#f59e0b' },
  '위험시설':       { label: '위험시설',       color: '#ef4444', superGroup: '위험/산업 인프라' },
  '에너지/발전시설': { label: '에너지/발전시설', color: '#a855f7', superGroup: '위험/산업 인프라' },
  '산업공정/제조시설': { label: '산업공정/제조시설', color: '#0ea5e9', superGroup: '위험/산업 인프라' },
};

const SUPER_GROUP_META: Record<string, { label: string; color: string }> = {
  '위험/산업 인프라': { label: '위험/산업 인프라', color: '#f97316' },
};

interface OverseasItem {
  key: string;
  label: string;
  color: string;
  count?: number;
  children?: OverseasItem[];
}

function countOverseasActiveLeaves(items: OverseasItem[], layers: Record<string, boolean>): number {
  let count = 0;
  for (const item of items) {
    if (item.children?.length) {
      count += countOverseasActiveLeaves(item.children, layers);
    } else if (layers[item.key]) {
      count += (item.count ?? 1);
    }
  }
  return count;
}

// ── Tree helpers ──────────────────────────────────────

function getAllLeafKeys(node: LayerTreeNode): string[] {
  if (!node.children) return [node.key];
  return node.children.flatMap(getAllLeafKeys);
}

function isNodeActive(node: LayerTreeNode, layers: Record<string, boolean>): boolean {
  if (!node.children) return !!layers[node.key];
  return node.children.some(c => isNodeActive(c, layers));
}

function getTreeCount(node: LayerTreeNode, layers: Record<string, boolean>): number {
  if (!node.children) return node.count ?? 0;
  return node.children.reduce((sum, c) => {
    if (!c.children && !layers[c.key]) return sum;
    if (c.children && !isNodeActive(c, layers)) return sum;
    return sum + getTreeCount(c, layers);
  }, 0);
}

// ── Props ─────────────────────────────────────────────

interface LayerPanelProps {
  layers: Record<string, boolean>;
  onToggle: (key: string) => void;
  onBatchToggle?: (keys: string[], value: boolean) => void;
  aircraftByCategory: Record<string, number>;
  aircraftTotal: number;
  shipsByMtCategory: Record<string, number>;
  shipTotal: number;
  satelliteCount: number;
  tree?: LayerTreeNode[];
  extraLayers?: ExtraLayer[];
  overseasItems?: OverseasItem[];
  hiddenAcCategories: Set<string>;
  hiddenShipCategories: Set<string>;
  onAcCategoryToggle: (cat: string) => void;
  onShipCategoryToggle: (cat: string) => void;
  shipsByNationality?: Record<string, number>;
  hiddenNationalities?: Set<string>;
  onNationalityToggle?: (nat: string) => void;
  fishingByNationality?: Record<string, number>;
  hiddenFishingNats?: Set<string>;
  onFishingNatToggle?: (nat: string) => void;
}

// ── Special renderer props (shared across recursive calls) ──

interface SpecialRendererProps {
  shipsByMtCategory: Record<string, number>;
  hiddenShipCategories: Set<string>;
  onShipCategoryToggle: (cat: string) => void;
  aircraftByCategory: Record<string, number>;
  hiddenAcCategories: Set<string>;
  onAcCategoryToggle: (cat: string) => void;
  fishingByNationality?: Record<string, number>;
  hiddenFishingNats?: Set<string>;
  onFishingNatToggle?: (nat: string) => void;
  shipsByNationality?: Record<string, number>;
  hiddenNationalities?: Set<string>;
  onNationalityToggle?: (nat: string) => void;
  legendOpen: Set<string>;
  toggleLegend: (key: string) => void;
  expanded: Set<string>;
  toggleExpand: (key: string) => void;
}

// ── Ship categories special renderer ─────────────────

function ShipCategoriesContent({
  shipsByMtCategory,
  hiddenShipCategories,
  onShipCategoryToggle,
  fishingByNationality,
  hiddenFishingNats,
  onFishingNatToggle,
  shipsByNationality,
  legendOpen,
  toggleLegend,
  expanded,
  toggleExpand,
}: {
  shipsByMtCategory: Record<string, number>;
  hiddenShipCategories: Set<string>;
  onShipCategoryToggle: (cat: string) => void;
  fishingByNationality?: Record<string, number>;
  hiddenFishingNats?: Set<string>;
  onFishingNatToggle?: (nat: string) => void;
  shipsByNationality?: Record<string, number>;
  legendOpen: Set<string>;
  toggleLegend: (key: string) => void;
  expanded: Set<string>;
  toggleExpand: (key: string) => void;
}) {
  const { t } = useTranslation(['common', 'ships']);
  return (
    <div className="layer-tree-children">
      {MT_CATEGORIES.map(cat => {
        const count = shipsByMtCategory[cat] || 0;
        if (count === 0) return null;

        if (cat === 'fishing' && fishingByNationality && hiddenFishingNats && onFishingNatToggle) {
          const isFishingExpanded = expanded.has('fishing-sub');
          return (
            <div key={cat}>
              <div style={{ display: 'flex', alignItems: 'center' }}>
                <span
                  style={{ fontSize: 7, color: 'var(--kcg-dim)', width: 10, textAlign: 'center', cursor: 'pointer', flexShrink: 0 }}
                  onClick={(e) => { e.stopPropagation(); toggleExpand('fishing-sub'); }}
                >
                  {isFishingExpanded ? '▼' : '▶'}
                </span>
                <div style={{ flex: 1 }}>
                  <CategoryToggle
                    label={t(`ships:mtType.${cat}`, cat.toUpperCase())}
                    color={MT_CAT_COLORS[cat] || 'var(--kcg-muted)'}
                    count={count}
                    hidden={hiddenShipCategories.has(cat)}
                    onClick={() => onShipCategoryToggle(cat)}
                  />
                </div>
              </div>
              {isFishingExpanded && !hiddenShipCategories.has('fishing') && (
                <div style={{ paddingLeft: 14 }}>
                  {FISHING_NAT_CATEGORIES.map(nat => {
                    const fCount = fishingByNationality[nat] || 0;
                    if (fCount === 0) return null;
                    return (
                      <CategoryToggle
                        key={`fishing-${nat}`}
                        label={FISHING_NAT_LABELS[nat] || nat}
                        color={FISHING_NAT_COLORS[nat] || '#888'}
                        count={fCount}
                        hidden={hiddenFishingNats.has(nat)}
                        onClick={() => onFishingNatToggle(nat)}
                      />
                    );
                  })}
                </div>
              )}
            </div>
          );
        }

        return (
          <CategoryToggle
            key={cat}
            label={t(`ships:mtType.${cat}`, cat.toUpperCase())}
            color={MT_CAT_COLORS[cat] || 'var(--kcg-muted)'}
            count={count}
            hidden={hiddenShipCategories.has(cat)}
            onClick={() => onShipCategoryToggle(cat)}
          />
        );
      })}

      {shipsByNationality && (
        <>
          <button
            type="button"
            className="legend-toggle"
            onClick={() => toggleLegend('shipType')}
          >
            {legendOpen.has('shipType') ? '\u25BC' : '\u25B6'} {t('legend.vesselType')}
          </button>
          {legendOpen.has('shipType') && (
            <div className="legend-content">
              <div className="flex flex-col gap-px text-[9px] opacity-85">
                {SHIP_TYPE_LEGEND.map(([key, color]) => (
                  <div key={key} className="flex items-center gap-1.5">
                    <span
                      className="shrink-0"
                      style={{
                        width: 0, height: 0,
                        borderLeft: '5px solid transparent',
                        borderRight: '5px solid transparent',
                        borderBottom: `10px solid ${color}`,
                      }}
                    />
                    <span className="text-kcg-text">{t(`ships:mtType.${key}`, key)}</span>
                  </div>
                ))}
              </div>
            </div>
          )}
        </>
      )}
    </div>
  );
}

// ── Aircraft categories special renderer ──────────────

function AircraftCategoriesContent({
  aircraftByCategory,
  hiddenAcCategories,
  onAcCategoryToggle,
  legendOpen,
  toggleLegend,
}: {
  aircraftByCategory: Record<string, number>;
  hiddenAcCategories: Set<string>;
  onAcCategoryToggle: (cat: string) => void;
  legendOpen: Set<string>;
  toggleLegend: (key: string) => void;
}) {
  const { t } = useTranslation(['common', 'ships']);
  return (
    <div className="layer-tree-children">
      {AC_CATEGORIES.map(cat => {
        const count = aircraftByCategory[cat] || 0;
        if (count === 0) return null;
        return (
          <CategoryToggle
            key={cat}
            label={t(`ships:aircraft.${cat}`, cat.toUpperCase())}
            color={AC_CAT_COLORS[cat] || '#888'}
            count={count}
            hidden={hiddenAcCategories.has(cat)}
            onClick={() => onAcCategoryToggle(cat)}
          />
        );
      })}
      <button type="button" className="legend-toggle" onClick={() => toggleLegend('altitude')}>
        {legendOpen.has('altitude') ? '\u25BC' : '\u25B6'} {t('legend.altitude')}
      </button>
      {legendOpen.has('altitude') && (
        <div className="legend-content">
          <div className="flex flex-col gap-px text-[9px] opacity-85">
            {ALT_LEGEND.map(([label, color]) => (
              <div key={label} className="flex items-center gap-1.5">
                <span className="inline-block w-2.5 h-2.5 shrink-0 rounded-sm" style={{ background: color }} />
                <span className="text-kcg-text">{label}</span>
              </div>
            ))}
          </div>
        </div>
      )}
      <button type="button" className="legend-toggle" onClick={() => toggleLegend('military')}>
        {legendOpen.has('military') ? '\u25BC' : '\u25B6'} {t('legend.military')}
      </button>
      {legendOpen.has('military') && (
        <div className="legend-content">
          <div className="flex flex-col gap-px text-[9px] opacity-85">
            {MIL_LEGEND.map(([label, color]) => (
              <div key={label} className="flex items-center gap-1.5">
                <span className="inline-block w-2.5 h-2.5 shrink-0 rounded-sm" style={{ background: color }} />
                <span className="text-kcg-text">{label}</span>
              </div>
            ))}
          </div>
        </div>
      )}
    </div>
  );
}

// ── Nationality categories special renderer ───────────

function NationalityCategoriesContent({
  shipsByNationality,
  hiddenNationalities,
  onNationalityToggle,
}: {
  shipsByNationality: Record<string, number>;
  hiddenNationalities: Set<string>;
  onNationalityToggle: (nat: string) => void;
}) {
  return (
    <div className="layer-tree-children">
      {NAT_CATEGORIES.map(nat => {
        const count = shipsByNationality[nat] || 0;
        if (count === 0) return null;
        return (
          <CategoryToggle
            key={nat}
            label={NAT_LABELS[nat] || nat}
            color={NAT_COLORS[nat] || '#888'}
            count={count}
            hidden={hiddenNationalities.has(nat)}
            onClick={() => onNationalityToggle(nat)}
          />
        );
      })}
    </div>
  );
}

// ── Recursive tree renderer ───────────────────────────

interface LayerTreeRendererProps {
  node: LayerTreeNode;
  depth: number;
  layers: Record<string, boolean>;
  expanded: Set<string>;
  onToggle: (key: string) => void;
  onBatchToggle?: (keys: string[], value: boolean) => void;
  toggleExpand: (key: string) => void;
  special: SpecialRendererProps;
}

function LayerTreeRenderer({
  node,
  depth,
  layers,
  expanded,
  onToggle,
  onBatchToggle,
  toggleExpand,
  special,
}: LayerTreeRendererProps) {
  const isLeaf = !node.children && !node.specialRenderer;
  const hasSpecial = !!node.specialRenderer;
  const isExpandable = !isLeaf;
  const active = isLeaf ? !!layers[node.key] : isNodeActive(node, layers);
  const count = isLeaf ? node.count : getTreeCount(node, layers);
  const isExp = expanded.has(node.key);

  const handleToggle = () => {
    if (isLeaf) {
      onToggle(node.key);
      return;
    }
    if (hasSpecial) {
      // Special nodes (ships/aircraft) toggle the underlying layer key
      onToggle(node.key);
      return;
    }
    // Parent cascade: toggle all leaf keys under this node
    const leaves = getAllLeafKeys(node);
    const allOn = leaves.every(k => layers[k]);
    if (onBatchToggle) {
      onBatchToggle(leaves, !allOn);
    } else {
      for (const k of leaves) {
        if (allOn || !layers[k]) onToggle(k);
      }
    }
  };

  const renderChildren = () => {
    if (node.specialRenderer === 'shipCategories') {
      return (
        <ShipCategoriesContent
          shipsByMtCategory={special.shipsByMtCategory}
          hiddenShipCategories={special.hiddenShipCategories}
          onShipCategoryToggle={special.onShipCategoryToggle}
          fishingByNationality={special.fishingByNationality}
          hiddenFishingNats={special.hiddenFishingNats}
          onFishingNatToggle={special.onFishingNatToggle}
          shipsByNationality={special.shipsByNationality}
          legendOpen={special.legendOpen}
          toggleLegend={special.toggleLegend}
          expanded={special.expanded}
          toggleExpand={special.toggleExpand}
        />
      );
    }
    if (node.specialRenderer === 'aircraftCategories') {
      return (
        <AircraftCategoriesContent
          aircraftByCategory={special.aircraftByCategory}
          hiddenAcCategories={special.hiddenAcCategories}
          onAcCategoryToggle={special.onAcCategoryToggle}
          legendOpen={special.legendOpen}
          toggleLegend={special.toggleLegend}
        />
      );
    }
    if (node.specialRenderer === 'nationalityCategories') {
      if (!special.shipsByNationality || !special.hiddenNationalities || !special.onNationalityToggle) return null;
      return (
        <NationalityCategoriesContent
          shipsByNationality={special.shipsByNationality}
          hiddenNationalities={special.hiddenNationalities}
          onNationalityToggle={special.onNationalityToggle}
        />
      );
    }
    if (node.children) {
      return (
        <div className="layer-tree-children">
          {node.children.map(child => (
            <LayerTreeRenderer
              key={child.key}
              node={child}
              depth={depth + 1}
              layers={layers}
              expanded={expanded}
              onToggle={onToggle}
              onBatchToggle={onBatchToggle}
              toggleExpand={toggleExpand}
              special={special}
            />
          ))}
        </div>
      );
    }
    return null;
  };

  return (
    <div style={depth > 0 ? { marginLeft: depth > 1 ? 12 : 0 } : undefined}>
      <LayerTreeItem
        layerKey={node.key}
        label={node.label}
        color={node.color}
        active={active}
        expandable={isExpandable}
        isExpanded={isExp}
        count={count}
        onToggle={handleToggle}
        onExpand={isExpandable ? () => toggleExpand(node.key) : undefined}
      />
      {isExpandable && isExp && renderChildren()}
    </div>
  );
}

// ── Main component ────────────────────────────────────

export function LayerPanel({
  layers,
  onToggle,
  onBatchToggle,
  aircraftByCategory,
  aircraftTotal,
  shipsByMtCategory,
  shipTotal,
  satelliteCount,
  tree,
  extraLayers,
  overseasItems,
  hiddenAcCategories,
  hiddenShipCategories,
  onAcCategoryToggle,
  onShipCategoryToggle,
  shipsByNationality,
  hiddenNationalities,
  onNationalityToggle,
  fishingByNationality,
  hiddenFishingNats,
  onFishingNatToggle,
}: LayerPanelProps) {
  const { t } = useTranslation(['common', 'ships']);
  const [expanded, setExpanded] = useLocalStorageSet('layerPanelExpanded', new Set(['ships']));
  const [legendOpen, setLegendOpen] = useState<Set<string>>(new Set());

  const toggleExpand = useCallback((key: string) => {
    setExpanded(prev => {
      const next = new Set(prev);
      if (next.has(key)) { next.delete(key); } else { next.add(key); }
      return next;
    });
  }, [setExpanded]);

  const toggleLegend = useCallback((key: string) => {
    setLegendOpen(prev => {
      const next = new Set(prev);
      if (next.has(key)) { next.delete(key); } else { next.add(key); }
      return next;
    });
  }, []);

  const _militaryCount = Object.entries(aircraftByCategory)
    .filter(([cat]) => cat !== 'civilian' && cat !== 'unknown')
    .reduce((sum, [, c]) => sum + c, 0);
  void _militaryCount;

  const specialProps: SpecialRendererProps = {
    shipsByMtCategory,
    hiddenShipCategories,
    onShipCategoryToggle,
    aircraftByCategory,
    hiddenAcCategories,
    onAcCategoryToggle,
    fishingByNationality,
    hiddenFishingNats,
    onFishingNatToggle,
    shipsByNationality,
    hiddenNationalities,
    onNationalityToggle,
    legendOpen,
    toggleLegend,
    expanded,
    toggleExpand,
  };

  return (
    <div className="layer-panel">
      <h3>LAYERS</h3>
      <div className="layer-items">
        {tree ? (
          // ── Unified tree rendering ──
          tree.map(node => (
            <LayerTreeRenderer
              key={node.key}
              node={node}
              depth={0}
              layers={layers}
              expanded={expanded}
              onToggle={onToggle}
              onBatchToggle={onBatchToggle}
              toggleExpand={toggleExpand}
              special={specialProps}
            />
          ))
        ) : (
          // ── Legacy rendering (backward compat) ──
          <>
            {/* Ships tree */}
            <LayerTreeItem
              layerKey="ships"
              label={t('layers.ships')}
              count={shipTotal}
              color="#fb923c"
              active={layers.ships}
              expandable
              isExpanded={expanded.has('ships')}
              onToggle={() => onToggle('ships')}
              onExpand={() => toggleExpand('ships')}
            />
            {layers.ships && expanded.has('ships') && (
              <ShipCategoriesContent
                shipsByMtCategory={shipsByMtCategory}
                hiddenShipCategories={hiddenShipCategories}
                onShipCategoryToggle={onShipCategoryToggle}
                fishingByNationality={fishingByNationality}
                hiddenFishingNats={hiddenFishingNats}
                onFishingNatToggle={onFishingNatToggle}
                shipsByNationality={shipsByNationality}
                legendOpen={legendOpen}
                toggleLegend={toggleLegend}
                expanded={expanded}
                toggleExpand={toggleExpand}
              />
            )}

            {/* Nationality tree (Korea tab only) */}
            {shipsByNationality && hiddenNationalities && onNationalityToggle && (
              <>
                <LayerTreeItem
                  layerKey="nationality"
                  label="국적 분류"
                  count={Object.values(shipsByNationality).reduce((a, b) => a + b, 0)}
                  color="#8b5cf6"
                  active
                  expandable
                  isExpanded={expanded.has('nationality')}
                  onToggle={() => toggleExpand('nationality')}
                  onExpand={() => toggleExpand('nationality')}
                />
                {expanded.has('nationality') && (
                  <NationalityCategoriesContent
                    shipsByNationality={shipsByNationality}
                    hiddenNationalities={hiddenNationalities}
                    onNationalityToggle={onNationalityToggle}
                  />
                )}
              </>
            )}

            {/* 항공망 그룹 */}
            <LayerTreeItem
              layerKey="group-항공망"
              label="항공망"
              color="#22d3ee"
              active
              expandable
              isExpanded={expanded.has('group-항공망')}
              onToggle={() => toggleExpand('group-항공망')}
              onExpand={() => toggleExpand('group-항공망')}
            />
            {expanded.has('group-항공망') && (
              <div className="layer-tree-children">
                <LayerTreeItem
                  layerKey="aircraft"
                  label={t('layers.aircraft')}
                  count={aircraftTotal}
                  color="#22d3ee"
                  active={layers.aircraft}
                  expandable
                  isExpanded={expanded.has('aircraft')}
                  onToggle={() => onToggle('aircraft')}
                  onExpand={() => toggleExpand('aircraft')}
                />
                {layers.aircraft && expanded.has('aircraft') && (
                  <AircraftCategoriesContent
                    aircraftByCategory={aircraftByCategory}
                    hiddenAcCategories={hiddenAcCategories}
                    onAcCategoryToggle={onAcCategoryToggle}
                    legendOpen={legendOpen}
                    toggleLegend={toggleLegend}
                  />
                )}
                <LayerTreeItem
                  layerKey="satellites"
                  label={t('layers.satellites')}
                  count={satelliteCount}
                  color="#ef4444"
                  active={layers.satellites}
                  onToggle={() => onToggle('satellites')}
                />
              </div>
            )}

            {/* Extra layers — grouped */}
            {extraLayers && (() => {
              const grouped: Record<string, ExtraLayer[]> = {};
              const ungrouped: ExtraLayer[] = [];
              for (const el of extraLayers) {
                if (el.group) {
                  if (!grouped[el.group]) grouped[el.group] = [];
                  grouped[el.group].push(el);
                } else {
                  ungrouped.push(el);
                }
              }

              const superGrouped: Record<string, string[]> = {};
              const noSuperGroup: string[] = [];
              for (const groupName of Object.keys(grouped)) {
                const sg = GROUP_META[groupName]?.superGroup;
                if (sg) {
                  if (!superGrouped[sg]) superGrouped[sg] = [];
                  superGrouped[sg].push(groupName);
                } else {
                  noSuperGroup.push(groupName);
                }
              }

              const renderGroup = (groupName: string, indent = false) => {
                const meta = GROUP_META[groupName] || { label: groupName, color: '#888' };
                const isGroupExpanded = expanded.has(`group-${groupName}`);
                const items = grouped[groupName] || [];
                return (
                  <div key={groupName} style={indent ? { paddingLeft: 10 } : undefined}>
                    <LayerTreeItem
                      layerKey={`group-${groupName}`}
                      label={meta.label}
                      color={meta.color}
                      active
                      expandable
                      isExpanded={isGroupExpanded}
                      onToggle={() => toggleExpand(`group-${groupName}`)}
                      onExpand={() => toggleExpand(`group-${groupName}`)}
                    />
                    {isGroupExpanded && (
                      <div className="layer-tree-children">
                        {items.map(el => (
                          <LayerTreeItem
                            key={el.key}
                            layerKey={el.key}
                            label={el.label}
                            count={el.count}
                            color={el.color}
                            active={layers[el.key] ?? false}
                            onToggle={() => onToggle(el.key)}
                          />
                        ))}
                      </div>
                    )}
                  </div>
                );
              };

              return (
                <>
                  {noSuperGroup.map(g => renderGroup(g))}
                  {Object.entries(superGrouped).map(([sgName, groupNames]) => {
                    const sgMeta = SUPER_GROUP_META[sgName] || { label: sgName, color: '#f97316' };
                    const isSgExpanded = expanded.has(`supergroup-${sgName}`);
                    return (
                      <div key={sgName}>
                        <LayerTreeItem
                          layerKey={`supergroup-${sgName}`}
                          label={sgMeta.label}
                          color={sgMeta.color}
                          active
                          expandable
                          isExpanded={isSgExpanded}
                          onToggle={() => toggleExpand(`supergroup-${sgName}`)}
                          onExpand={() => toggleExpand(`supergroup-${sgName}`)}
                        />
                        {isSgExpanded && (
                          <div className="layer-tree-children">
                            {groupNames.map(g => renderGroup(g, true))}
                          </div>
                        )}
                      </div>
                    );
                  })}
                  {ungrouped.map(el => (
                    <LayerTreeItem
                      key={el.key}
                      layerKey={el.key}
                      label={el.label}
                      count={el.count}
                      color={el.color}
                      active={layers[el.key] ?? false}
                      onToggle={() => onToggle(el.key)}
                    />
                  ))}
                </>
              );
            })()}

            <div className="layer-divider" />

            {/* 해외시설 */}
            <LayerTreeItem
              layerKey="overseas-section"
              label="해외시설"
              count={overseasItems ? countOverseasActiveLeaves(overseasItems, layers) : 0}
              color="#f97316"
              active={expanded.has('overseas-section')}
              expandable
              isExpanded={expanded.has('overseas-section')}
              onToggle={() => toggleExpand('overseas-section')}
              onExpand={() => toggleExpand('overseas-section')}
            />
            {expanded.has('overseas-section') && overseasItems && overseasItems.length > 0 && (
              <div className="layer-tree-children">
                {overseasItems.map(item => (
                  <OverseasTreeNode
                    key={item.key}
                    item={item}
                    depth={0}
                    layers={layers}
                    expanded={expanded}
                    onToggle={onToggle}
                    onToggleAll={onToggle}
                    toggleExpand={toggleExpand}
                  />
                ))}
              </div>
            )}
          </>
        )}
      </div>
      <FontScalePanel />
    </div>
  );
}

/* ── Overseas 3-level tree node ────────────────────── */

function OverseasTreeNode({ item, depth, layers, expanded, onToggle, onToggleAll, toggleExpand }: {
  item: OverseasItem;
  depth: number;
  layers: Record<string, boolean>;
  expanded: Set<string>;
  onToggle: (key: string) => void;
  onToggleAll: (key: string) => void;
  toggleExpand: (key: string) => void;
}) {
  const hasChildren = item.children && item.children.length > 0;
  const isExpanded = expanded.has(item.key);
  const isActive = hasChildren
    ? item.children!.some(c => c.children?.length ? c.children.some(gc => layers[gc.key]) : layers[c.key])
    : layers[item.key];
  const leafCount = hasChildren ? countOverseasActiveLeaves([item], layers) : (item.count ?? 0);

  const handleToggle = () => {
    if (hasChildren) {
      const allLeaves: string[] = [];
      const collectLeaves = (node: OverseasItem) => {
        if (node.children?.length) node.children.forEach(collectLeaves);
        else allLeaves.push(node.key);
      };
      collectLeaves(item);
      const allOn = allLeaves.every(k => layers[k]);
      for (const k of allLeaves) {
        if (allOn || !layers[k]) onToggleAll(k);
      }
    } else {
      onToggle(item.key);
    }
  };

  return (
    <div style={{ marginLeft: depth * 12 }}>
      <LayerTreeItem
        layerKey={item.key}
        label={item.label}
        color={item.color}
        active={!!isActive}
        expandable={!!hasChildren}
        isExpanded={isExpanded}
        count={leafCount}
        onToggle={handleToggle}
        onExpand={() => toggleExpand(item.key)}
      />
      {hasChildren && isExpanded && (
        <div className="layer-tree-children">
          {item.children!.map(child => (
            <OverseasTreeNode
              key={child.key}
              item={child}
              depth={depth + 1}
              layers={layers}
              expanded={expanded}
              onToggle={onToggle}
              onToggleAll={onToggleAll}
              toggleExpand={toggleExpand}
            />
          ))}
        </div>
      )}
    </div>
  );
}

/* ── Sub-components ─────────────────────────────────── */

function LayerTreeItem({
  layerKey,
  label,
  color,
  active,
  expandable,
  isExpanded,
  count,
  onToggle,
  onExpand,
}: {
  layerKey: string;
  label: string;
  color: string;
  active: boolean;
  expandable?: boolean;
  isExpanded?: boolean;
  count?: number;
  onToggle: () => void;
  onExpand?: () => void;
}) {
  return (
    <div className="layer-tree-header" data-layer={layerKey}>
      {expandable ? (
        <span
          className={`layer-tree-arrow ${isExpanded ? 'expanded' : ''}`}
          onClick={e => { e.stopPropagation(); onExpand?.(); }}
        >
          {'\u25B6'}
        </span>
      ) : (
        <span className="layer-tree-arrow" />
      )}
      <button
        type="button"
        className={`layer-toggle ${active ? 'active' : ''}`}
        onClick={onToggle}
        style={{ padding: 0, gap: '6px', flex: 1, width: '100%' }}
      >
        <span
          className="layer-dot"
          style={{ backgroundColor: active ? color : '#444' }}
        />
        <span style={{ flex: 1 }}>{label}</span>
        {count != null && (
          <span style={{ fontSize: 9, color: 'var(--kcg-dim)', flexShrink: 0 }}>{count}</span>
        )}
      </button>
    </div>
  );
}

function CategoryToggle({
  label,
  color,
  count,
  hidden,
  onClick,
}: {
  label: string;
  color: string;
  count: number;
  hidden: boolean;
  onClick: () => void;
}) {
  return (
    <div
      className={`category-toggle ${hidden ? 'hidden' : ''}`}
      onClick={onClick}
    >
      <span className="category-dot" style={{ backgroundColor: color }} />
      <span className="category-label">{label}</span>
      <span className="category-count">{count}</span>
    </div>
  );
}
