import { useEffect, useState } from 'react';
import { ToggleButton, Section } from '@wing/ui';
import type { AisTarget } from '../../entities/aisTarget/model/types';
import type { LegacyVesselIndex } from '../../entities/legacyVessel/lib';
import type { LegacyVesselDataset, LegacyVesselInfo } from '../../entities/legacyVessel/model/types';
import type { VesselTypeCode } from '../../entities/vessel/model/types';
import { VESSEL_TYPE_ORDER } from '../../entities/vessel/model/meta';
import type { ZonesGeoJson } from '../../entities/zone/api/useZones';
import type { AisPollingSnapshot } from '../../features/aisPolling/useAisTargetPolling';
import { Map3DSettingsToggles } from '../../features/map3dSettings/Map3DSettingsToggles';
import type { DerivedLegacyVessel, LegacyAlarm, LegacyAlarmKind } from '../../features/legacyDashboard/model/types';
import { LEGACY_ALARM_KIND_LABEL, LEGACY_ALARM_KINDS } from '../../features/legacyDashboard/model/types';
import { MapToggles } from '../../features/mapToggles/MapToggles';
import { TypeFilterGrid } from '../../features/typeFilter/TypeFilterGrid';
import { AisTargetList } from '../../widgets/aisTargetList/AisTargetList';
import { AlarmsPanel } from '../../widgets/alarms/AlarmsPanel';
import { RelationsPanel } from '../../widgets/relations/RelationsPanel';
import { SpeedProfilePanel } from '../../widgets/speed/SpeedProfilePanel';
import { VesselList } from '../../widgets/vesselList/VesselList';
import { fmtIsoFull } from '../../shared/lib/datetime';
import type { useDashboardState } from './useDashboardState';
import type { Bbox } from './useDashboardState';

const AIS_API_BASE = (import.meta.env.VITE_API_URL || '/snp-api').replace(/\/$/, '');

function fmtBbox(b: Bbox | null) {
  if (!b) return '-';
  return `${b[0].toFixed(4)},${b[1].toFixed(4)},${b[2].toFixed(4)},${b[3].toFixed(4)}`;
}

interface DashboardSidebarProps {
  isOpen: boolean;
  onClose: () => void;
  state: ReturnType<typeof useDashboardState>;
  legacyVesselsAll: DerivedLegacyVessel[];
  legacyVesselsFiltered: DerivedLegacyVessel[];
  legacyCounts: Record<VesselTypeCode, number>;
  selectedLegacyVessel: DerivedLegacyVessel | null;
  activeHighlightedMmsiSet: number[];
  legacyHits: Map<number, LegacyVesselInfo>;
  filteredAlarms: LegacyAlarm[];
  alarms: LegacyAlarm[];
  alarmKindCounts: Record<LegacyAlarmKind, number>;
  speedPanelType: VesselTypeCode;
  onFleetContextMenu: (ownerKey: string, mmsis: number[]) => void;
  snapshot: AisPollingSnapshot;
  legacyError: string | null;
  legacyData: LegacyVesselDataset | null;
  targetsInScope: AisTarget[];
  zonesError: string | null;
  zones: ZonesGeoJson | null;
  legacyIndex: LegacyVesselIndex | null;
}

export function DashboardSidebar({
  isOpen,
  onClose,
  state,
  legacyVesselsAll,
  legacyVesselsFiltered,
  legacyCounts,
  selectedLegacyVessel,
  activeHighlightedMmsiSet,
  legacyHits,
  filteredAlarms,
  alarms,
  alarmKindCounts,
  speedPanelType,
  onFleetContextMenu,
  snapshot,
  legacyError,
  legacyData,
  targetsInScope,
  zonesError,
  zones,
  legacyIndex,
}: DashboardSidebarProps) {
  const {
    showTargets, setShowTargets, showOthers, setShowOthers,
    typeEnabled, setTypeEnabled,
    overlays, setOverlays,
    projection, setProjection, isProjectionToggleDisabled,
    freeCamera, toggleFreeCamera,
    baseMap, setBaseMap,
    selectedMmsi, setSelectedMmsi,
    fleetRelationSortMode, setFleetRelationSortMode,
    hoveredFleetOwnerKey, hoveredFleetMmsiSet,
    setHoveredMmsiSet, setHoveredPairMmsiSet,
    setHoveredFleetOwnerKey, setHoveredFleetMmsiSet,
    alarmKindEnabled, setAlarmKindEnabled,
    adminMode,
    viewBbox, useViewportFilter, setUseViewportFilter,
    useApiBbox, setUseApiBbox, setApiBbox,
    settings, setSettings,
    setUniqueSorted, setSortedIfChanged, toggleHighlightedMmsi,
  } = state;

  const [isAlarmFilterOpen, setIsAlarmFilterOpen] = useState(false);

  useEffect(() => {
    if (!isOpen) return;
    const handler = (e: KeyboardEvent) => { if (e.key === 'Escape') onClose(); };
    document.addEventListener('keydown', handler);
    return () => document.removeEventListener('keydown', handler);
  }, [isOpen, onClose]);

  return (
    <>
      {isOpen && (
        <div className="fixed inset-0 z-[1100] bg-black/50 md:hidden" onClick={onClose} aria-hidden />
      )}

      <div
        className={`
          fixed inset-y-0 left-0 z-[1200] w-[310px] max-w-[100vw] transform overflow-y-auto
          border-r border-wing-border bg-wing-surface transition-transform duration-200
          ${isOpen ? 'translate-x-0' : '-translate-x-full'}
          md:static md:z-auto md:translate-x-0 md:transition-none md:overflow-hidden md:flex md:flex-col
        `}
      >
        <div className="h-[44px] md:hidden" />

        <Section title="업종 필터" className="md:shrink-0">
          <div className="flex flex-wrap gap-0.75 mb-1.5">
            <ToggleButton
              on={showTargets}
              onClick={() => {
                setShowTargets((v) => {
                  const next = !v;
                  if (!next) setSelectedMmsi((m) => (legacyHits.has(m ?? -1) ? null : m));
                  return next;
                });
              }}
              title="레거시(CN permit) 대상 선박 표시"
            >
              대상 선박
            </ToggleButton>
            <ToggleButton on={showOthers} onClick={() => setShowOthers((v) => !v)} title="대상 외 AIS 선박 표시">
              기타 AIS
            </ToggleButton>
          </div>
          <TypeFilterGrid
            enabled={typeEnabled}
            totalCount={legacyVesselsAll.length}
            countsByType={legacyCounts}
            onToggle={(code) => {
              if (selectedLegacyVessel && selectedLegacyVessel.shipCode === code && typeEnabled[code]) setSelectedMmsi(null);
              setTypeEnabled((prev) => ({ ...prev, [code]: !prev[code] }));
            }}
            onToggleAll={() => {
              const allOn = VESSEL_TYPE_ORDER.every((c) => typeEnabled[c]);
              const nextVal = !allOn;
              if (!nextVal && selectedLegacyVessel) setSelectedMmsi(null);
              setTypeEnabled({ PT: nextVal, 'PT-S': nextVal, GN: nextVal, OT: nextVal, PS: nextVal, FC: nextVal });
            }}
          />
        </Section>

        <Section
          title="지도 설정"
          className="md:shrink-0"
          actions={
            <div className="flex items-center gap-1">
              <ToggleButton
                on={freeCamera}
                onClick={toggleFreeCamera}
                title="자유 시점 모드 (회전/틸트 허용)"
                className="px-2 py-0.5 text-[9px]"
              >
                자유 시점
              </ToggleButton>
              <ToggleButton
                on={projection === 'globe'}
                onClick={isProjectionToggleDisabled ? undefined : () => setProjection((p) => (p === 'globe' ? 'mercator' : 'globe'))}
                title={isProjectionToggleDisabled ? '3D 모드 준비 중...' : '3D 지구본 투영'}
                className={`px-2 py-0.5 text-[9px]${isProjectionToggleDisabled ? " opacity-40 cursor-not-allowed" : ""}`}
              >
                3D
              </ToggleButton>
              <span className="mx-0.5 h-3 w-px bg-wing-border" />
              <ToggleButton
                on={baseMap === 'enhanced'}
                onClick={() => setBaseMap('enhanced')}
                title="기본 지도 (MapTiler Enhanced)"
                className="px-2 py-0.5 text-[9px]"
              >
                Base
              </ToggleButton>
              <ToggleButton
                on={baseMap === 'osm'}
                onClick={() => setBaseMap('osm')}
                title="OSM 기본 래스터 지도"
                className="px-2 py-0.5 text-[9px]"
              >
                OSM
              </ToggleButton>
              <ToggleButton
                on={baseMap === 'ocean'}
                onClick={() => setBaseMap('ocean')}
                title="Ocean 전용 지도 (해양 정보 극대화)"
                className="px-2 py-0.5 text-[9px]"
              >
                Ocean
              </ToggleButton>
            </div>
          }
        >
          <MapToggles value={overlays} onToggle={(k) => setOverlays((prev) => ({ ...prev, [k]: !prev[k] }))} />
        </Section>

        <Section title="속도 프로파일" defaultOpen={false} className="md:shrink-0">
          <SpeedProfilePanel selectedType={speedPanelType} />
        </Section>

        <Section
          title={
            <>
              선단 연관관계{' '}
              <span className="text-[8px] font-normal normal-case tracking-normal text-wing-accent">
                {selectedLegacyVessel ? `${selectedLegacyVessel.permitNo} 연관` : '(선박 클릭 시 표시)'}
              </span>
            </>
          }
          actions={
            <div className="relation-sort">
              <label className="relation-sort__option">
                <input type="radio" name="fleet-relation-sort" checked={fleetRelationSortMode === 'count'} onChange={() => setFleetRelationSortMode('count')} />
                척수
              </label>
              <label className="relation-sort__option">
                <input type="radio" name="fleet-relation-sort" checked={fleetRelationSortMode === 'range'} onChange={() => setFleetRelationSortMode('range')} />
                범위
              </label>
            </div>
          }
          className="md:shrink-0 max-h-[260px] flex flex-col overflow-hidden"
          contentClassName="flex-1 min-h-0 overflow-y-auto"
        >
          <RelationsPanel
            selectedVessel={selectedLegacyVessel}
            vessels={legacyVesselsAll}
            fleetVessels={legacyVesselsFiltered}
            onSelectMmsi={setSelectedMmsi}
            onToggleHighlightMmsi={toggleHighlightedMmsi}
            onHoverMmsi={(mmsis) => setHoveredMmsiSet(setUniqueSorted(mmsis))}
            onClearHover={() => setHoveredMmsiSet([])}
            onHoverPair={(pairMmsis) => setHoveredPairMmsiSet(setUniqueSorted(pairMmsis))}
            onClearPairHover={() => setHoveredPairMmsiSet([])}
            onHoverFleet={(ownerKey, fleetMmsis) => {
              setHoveredFleetOwnerKey(ownerKey);
              setHoveredFleetMmsiSet(setSortedIfChanged(fleetMmsis));
            }}
            onClearFleetHover={() => {
              setHoveredFleetOwnerKey(null);
              setHoveredFleetMmsiSet((prev) => (prev.length === 0 ? prev : []));
            }}
            fleetSortMode={fleetRelationSortMode}
            hoveredFleetOwnerKey={hoveredFleetOwnerKey}
            hoveredFleetMmsiSet={hoveredFleetMmsiSet}
            onContextMenuFleet={onFleetContextMenu}
          />
        </Section>

        <Section
          title={
            <>
              선박 목록{' '}
              <span className="text-[8px] font-normal normal-case tracking-normal text-wing-accent">({legacyVesselsFiltered.length}척)</span>
            </>
          }
          className="md:flex-1 md:min-h-0 flex flex-col overflow-hidden"
          contentClassName="md:flex-1 md:min-h-0 flex flex-col overflow-hidden"
        >
          <VesselList
            vessels={legacyVesselsFiltered}
            selectedMmsi={selectedMmsi}
            highlightedMmsiSet={activeHighlightedMmsiSet}
            onSelectMmsi={setSelectedMmsi}
            onToggleHighlightMmsi={toggleHighlightedMmsi}
            onHoverMmsi={(mmsi) => setHoveredMmsiSet([mmsi])}
            onClearHover={() => setHoveredMmsiSet([])}
          />
        </Section>

        <Section
          title={
            <>
              실시간 경고{' '}
              <span className="text-[8px] font-normal normal-case tracking-normal text-wing-accent">({filteredAlarms.length}/{alarms.length})</span>
            </>
          }
          actions={
            <ToggleButton on={isAlarmFilterOpen} onClick={() => setIsAlarmFilterOpen((v) => !v)}>
              필터
            </ToggleButton>
          }
          className="md:shrink-0 max-h-[180px] flex flex-col overflow-hidden"
          contentClassName="flex-1 min-h-0 overflow-y-auto"
        >
          {isAlarmFilterOpen && (
            <div className="flex flex-wrap gap-x-2.5 gap-y-1 mb-1.5">
              {LEGACY_ALARM_KINDS.map((k) => (
                <label key={k} className="inline-flex gap-1 items-center cursor-pointer select-none">
                  <input type="checkbox" checked={!!alarmKindEnabled[k]} onChange={() => setAlarmKindEnabled((prev) => ({ ...prev, [k]: !prev[k] }))} />
                  <span className="text-[8px] text-wing-muted whitespace-nowrap">
                    {LEGACY_ALARM_KIND_LABEL[k]} <span className="text-wing-text">{alarmKindCounts[k] ?? 0}</span>
                  </span>
                </label>
              ))}
            </div>
          )}
          <AlarmsPanel alarms={filteredAlarms} onSelectMmsi={setSelectedMmsi} />
        </Section>

        {adminMode ? (
          <>
            <Section title="ADMIN · AIS Target Polling" defaultOpen={false} className="md:shrink-0">
              <div style={{ fontSize: 11, lineHeight: 1.45 }}>
                <div style={{ color: 'var(--muted)', fontSize: 10 }}>엔드포인트</div>
                <div style={{ wordBreak: 'break-all' }}>{AIS_API_BASE}/api/ais-target/search</div>
                <div style={{ marginTop: 6, color: 'var(--muted)', fontSize: 10 }}>상태</div>
                <div>
                  <b style={{ color: snapshot.status === 'ready' ? 'var(--wing-success)' : snapshot.status === 'error' ? 'var(--wing-danger)' : 'var(--wing-warning)' }}>
                    {snapshot.status.toUpperCase()}
                  </b>
                  {snapshot.error ? <span style={{ marginLeft: 6, color: 'var(--wing-danger)' }}>{snapshot.error}</span> : null}
                </div>
                <div style={{ marginTop: 6, color: 'var(--muted)', fontSize: 10 }}>최근 fetch</div>
                <div>
                  {fmtIsoFull(snapshot.lastFetchAt)}{' '}
                  <span style={{ color: 'var(--muted)', fontSize: 10 }}>
                    ({snapshot.lastFetchMinutes ?? '-'}m, inserted {snapshot.lastInserted}, upserted {snapshot.lastUpserted})
                  </span>
                </div>
                <div style={{ marginTop: 6, color: 'var(--muted)', fontSize: 10 }}>메시지</div>
                <div style={{ color: 'var(--text)', fontSize: 10 }}>{snapshot.lastMessage ?? '-'}</div>
              </div>
            </Section>

            <Section title="ADMIN · Legacy (CN Permit)" defaultOpen={false} className="md:shrink-0">
              {legacyError ? (
                <div style={{ fontSize: 11, color: 'var(--wing-danger)' }}>legacy load error: {legacyError}</div>
              ) : (
                <div style={{ fontSize: 11, lineHeight: 1.45 }}>
                  <div style={{ color: 'var(--muted)', fontSize: 10 }}>데이터셋</div>
                  <div style={{ wordBreak: 'break-all', fontSize: 10 }}>/data/legacy/chinese-permitted.v1.json</div>
                  <div style={{ marginTop: 6, color: 'var(--muted)', fontSize: 10 }}>매칭(현재 scope)</div>
                  <div>
                    <b style={{ color: 'var(--wing-warning)' }}>{legacyVesselsAll.length}</b>{' '}
                    <span style={{ color: 'var(--muted)', fontSize: 10 }}>/ {targetsInScope.length}</span>
                  </div>
                  <div style={{ marginTop: 6, color: 'var(--muted)', fontSize: 10 }}>생성시각</div>
                  <div style={{ fontSize: 10, color: 'var(--text)' }}>{legacyData?.generatedAt ? fmtIsoFull(legacyData.generatedAt) : 'loading...'}</div>
                </div>
              )}
            </Section>

            <Section title="ADMIN · Viewport / BBox" defaultOpen={false} className="md:shrink-0">
              <div style={{ fontSize: 11, lineHeight: 1.45 }}>
                <div style={{ color: 'var(--muted)', fontSize: 10 }}>현재 View BBox</div>
                <div style={{ wordBreak: 'break-all', fontSize: 10 }}>{fmtBbox(viewBbox)}</div>
                <div style={{ marginTop: 8, display: 'flex', gap: 6, flexWrap: 'wrap' }}>
                  <button
                    onClick={() => setUseViewportFilter((v) => !v)}
                    style={{
                      fontSize: 10, padding: '4px 8px', borderRadius: 6,
                      border: '1px solid var(--border)',
                      background: useViewportFilter ? 'rgba(59,130,246,.18)' : 'var(--card)',
                      color: 'var(--text)', cursor: 'pointer',
                    }}
                    title="지도/리스트에 현재 화면 영역 내 선박만 표시(클라이언트 필터)"
                  >
                    Viewport filter {useViewportFilter ? 'ON' : 'OFF'}
                  </button>
                  <button
                    onClick={() => {
                      if (!viewBbox) return;
                      setUseApiBbox((v) => {
                        const next = !v;
                        if (next && viewBbox) setApiBbox(fmtBbox(viewBbox));
                        if (!next) setApiBbox(undefined);
                        return next;
                      });
                    }}
                    style={{
                      fontSize: 10, padding: '4px 8px', borderRadius: 6,
                      border: '1px solid var(--border)',
                      background: useApiBbox ? 'rgba(245,158,11,.14)' : 'var(--card)',
                      color: viewBbox ? 'var(--text)' : 'var(--muted)',
                      cursor: viewBbox ? 'pointer' : 'not-allowed',
                    }}
                    title="서버에서 bbox로 필터링해서 내려받기"
                    disabled={!viewBbox}
                  >
                    API bbox {useApiBbox ? 'ON' : 'OFF'}
                  </button>
                  <button
                    onClick={() => { if (!viewBbox) return; setApiBbox(fmtBbox(viewBbox)); setUseApiBbox(true); }}
                    style={{
                      fontSize: 10, padding: '4px 8px', borderRadius: 6,
                      border: '1px solid var(--border)', background: 'var(--card)',
                      color: viewBbox ? 'var(--text)' : 'var(--muted)', cursor: viewBbox ? 'pointer' : 'not-allowed',
                    }}
                    disabled={!viewBbox}
                    title="현재 view bbox로 API bbox를 갱신"
                  >
                    bbox=viewport
                  </button>
                </div>
                <div style={{ marginTop: 8, color: 'var(--muted)', fontSize: 10 }}>
                  표시 선박: <b style={{ color: 'var(--text)' }}>{targetsInScope.length}</b> / 스토어:{' '}
                  <b style={{ color: 'var(--text)' }}>{snapshot.total}</b>
                </div>
              </div>
            </Section>

            <Section title="ADMIN · Map (Extras)" defaultOpen={false} className="md:shrink-0">
              <Map3DSettingsToggles value={settings} onToggle={(k) => setSettings((prev) => ({ ...prev, [k]: !prev[k] }))} />
              <div style={{ fontSize: 10, color: 'var(--muted)', marginTop: 6 }}>단일 WebGL 컨텍스트: MapboxOverlay(interleaved)</div>
            </Section>

            <Section
              title="ADMIN · AIS Targets (All)"
              defaultOpen={false}
              className="md:shrink-0 md:max-h-[200px] flex flex-col md:overflow-hidden"
              contentClassName="md:flex-1 md:min-h-0 md:overflow-y-auto"
            >
              <AisTargetList targets={targetsInScope} selectedMmsi={selectedMmsi} onSelectMmsi={setSelectedMmsi} legacyIndex={legacyIndex} />
            </Section>

            <Section title="ADMIN · 수역 데이터" defaultOpen={false} className="md:shrink-0">
              {zonesError ? (
                <div style={{ fontSize: 11, color: 'var(--wing-danger)' }}>zones load error: {zonesError}</div>
              ) : (
                <div style={{ fontSize: 11, color: 'var(--muted)' }}>{zones ? `loaded (${zones.features.length} features)` : 'loading...'}</div>
              )}
            </Section>
          </>
        ) : null}
      </div>
    </>
  );
}
