import { useCallback, useState } from 'react';
import type { DerivedLegacyVessel } from '../../legacyDashboard/model/types';
import type { MultiTrackQueryContext } from '../../trackReplay/model/track.types';
import { useTrackQueryStore } from '../../trackReplay/stores/trackQueryStore';
import { MAX_VESSEL_SELECT, MAX_QUERY_DAYS } from '../model/types';
import type { VesselGroup } from '../model/types';
import { useVesselGroups } from './useVesselGroups';

/** ms → datetime-local input value (KST = UTC+9) */
function toDateTimeLocalKST(ms: number): string {
  const kstDate = new Date(ms + 9 * 3600_000);
  return kstDate.toISOString().slice(0, 16);
}

/** datetime-local value (KST) → ISO string */
function fromDateTimeLocalKST(value: string): string {
  return `${value}:00+09:00`;
}

const DEFAULT_DAYS = 7;

export interface VesselSelectModalState {
  isOpen: boolean;
  open: () => void;
  reopen: () => void;
  close: () => void;

  selectedMmsis: Set<number>;
  toggleMmsi: (mmsi: number) => void;
  setMmsis: (mmsis: Set<number>) => void;
  selectAllFiltered: (filtered: DerivedLegacyVessel[]) => void;
  clearAll: () => void;

  searchQuery: string;
  setSearchQuery: (q: string) => void;

  shipCodeFilter: Set<string>;
  toggleShipCode: (code: string) => void;
  toggleAllShipCodes: (allCodes: string[]) => void;

  onlySailing: boolean;
  setOnlySailing: (v: boolean) => void;

  stateFilter: Set<string>;
  toggleStateFilter: (label: string) => void;
  toggleAllStates: (allLabels: string[]) => void;

  startTime: string;
  endTime: string;
  setStartTime: (v: string) => void;
  setEndTime: (v: string) => void;
  applyPresetDays: (hours: number) => void;

  isQuerying: boolean;
  submitQuery: (allVessels: DerivedLegacyVessel[]) => void;

  position: { x: number; y: number };
  setPosition: (pos: { x: number; y: number }) => void;

  selectionWarning: string | null;

  groups: VesselGroup[];
  saveGroup: (name: string, mmsis: number[]) => string | null;
  deleteGroup: (id: string) => void;
  applyGroup: (group: VesselGroup) => void;
}

export function useVesselSelectModal(userId: number | null = null): VesselSelectModalState {
  const [isOpen, setIsOpen] = useState(false);
  const [selectedMmsis, setSelectedMmsis] = useState<Set<number>>(new Set());
  const [searchQuery, setSearchQuery] = useState('');
  const [shipCodeFilter, setShipCodeFilter] = useState<Set<string>>(new Set());
  const [onlySailing, setOnlySailing] = useState(false);
  const [stateFilter, setStateFilter] = useState<Set<string>>(new Set());
  const [selectionWarning, setSelectionWarning] = useState<string | null>(null);
  const [isQuerying, setIsQuerying] = useState(false);
  const [position, setPosition] = useState({ x: 0, y: 0 });

  const [startTime, setStartTime] = useState(() => {
    const n = Date.now();
    return toDateTimeLocalKST(n - DEFAULT_DAYS * 86_400_000);
  });
  const [endTime, setEndTime] = useState(() => toDateTimeLocalKST(Date.now()));

  const open = useCallback(() => {
    setIsOpen(true);
    setSelectedMmsis(new Set());
    setSearchQuery('');
    setShipCodeFilter(new Set());
    setOnlySailing(false);
    setStateFilter(new Set());
    setSelectionWarning(null);
    setIsQuerying(false);
    setPosition({ x: 0, y: 0 });
    const n = Date.now();
    setStartTime(toDateTimeLocalKST(n - DEFAULT_DAYS * 86_400_000));
    setEndTime(toDateTimeLocalKST(n));
  }, []);

  const reopen = useCallback(() => setIsOpen(true), []);

  const close = useCallback(() => setIsOpen(false), []);

  const toggleMmsi = useCallback((mmsi: number) => {
    setSelectedMmsis((prev) => {
      const next = new Set(prev);
      if (next.has(mmsi)) {
        next.delete(mmsi);
        setSelectionWarning(null);
      } else {
        if (next.size >= MAX_VESSEL_SELECT) {
          setSelectionWarning(`최대 ${MAX_VESSEL_SELECT}척까지 선택 가능합니다`);
          return prev;
        }
        next.add(mmsi);
        setSelectionWarning(null);
      }
      return next;
    });
  }, []);

  const setMmsis = useCallback((mmsis: Set<number>) => {
    if (mmsis.size > MAX_VESSEL_SELECT) {
      setSelectionWarning(`최대 ${MAX_VESSEL_SELECT}척까지 선택 가능합니다`);
      return;
    }
    setSelectedMmsis(mmsis);
    setSelectionWarning(null);
  }, []);

  const { groups, saveGroup, deleteGroup, applyGroup } = useVesselGroups(userId, setMmsis);

  const selectAllFiltered = useCallback((filtered: DerivedLegacyVessel[]) => {
    const capped = filtered.slice(0, MAX_VESSEL_SELECT);
    setSelectedMmsis(new Set(capped.map((v) => v.mmsi)));
    if (filtered.length > MAX_VESSEL_SELECT) {
      setSelectionWarning(`최대 ${MAX_VESSEL_SELECT}척까지 선택 가능합니다 (${filtered.length}척 중 ${MAX_VESSEL_SELECT}척 선택됨)`);
    } else {
      setSelectionWarning(null);
    }
  }, []);

  const clearAll = useCallback(() => {
    setSelectedMmsis(new Set());
    setSelectionWarning(null);
  }, []);

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

  const toggleAllShipCodes = useCallback((allCodes: string[]) => {
    setShipCodeFilter((prev) =>
      prev.size === allCodes.length ? new Set() : new Set(allCodes),
    );
  }, []);

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

  const toggleAllStates = useCallback((allLabels: string[]) => {
    setStateFilter((prev) =>
      prev.size === allLabels.length ? new Set() : new Set(allLabels),
    );
  }, []);

  const applyPresetDays = useCallback(
    (days: number) => {
      const now = Date.now();
      const spanMs = days * 86_400_000;

      // datetime-local (KST) → ms (UTC)
      const parseKST = (v: string) => new Date(`${v}:00+09:00`).getTime();
      const curStart = parseKST(startTime);
      const curEnd = parseKST(endTime);
      const curGap = curEnd - curStart;

      if (curGap > spanMs) {
        // 현재 간격이 프리셋보다 넓으면 → 시작을 종료 기준으로 조정
        const cappedEnd = Math.min(curEnd, now);
        setEndTime(toDateTimeLocalKST(cappedEnd));
        setStartTime(toDateTimeLocalKST(cappedEnd - spanMs));
      } else {
        // 시작 기준으로 종료 확장, 종료 max = 현재
        const newEnd = Math.min(curStart + spanMs, now);
        setEndTime(toDateTimeLocalKST(newEnd));
        // 종료가 clamp 되었으면 시작도 조정
        if (newEnd - curStart < spanMs) {
          setStartTime(toDateTimeLocalKST(newEnd - spanMs));
        }
      }
    },
    [startTime, endTime],
  );

  const submitQuery = useCallback(
    (allVessels: DerivedLegacyVessel[]) => {
      const selected = allVessels.filter((v) => selectedMmsis.has(v.mmsi));
      if (selected.length === 0) return;

      const maxMs = MAX_QUERY_DAYS * 86_400_000;
      const sMs = new Date(fromDateTimeLocalKST(startTime)).getTime();
      const eMs = new Date(fromDateTimeLocalKST(endTime)).getTime();
      if (eMs - sMs > maxMs) {
        const clampedEnd = toDateTimeLocalKST(sMs + maxMs);
        setEndTime(clampedEnd);
        setSelectionWarning(`최대 ${MAX_QUERY_DAYS}일 초과 — 종료일을 자동 조정했습니다`);
        return;
      }

      const vessels = selected.map((v) => ({
        mmsi: v.mmsi,
        shipNameHint: v.name,
        isPermitted: true,
        vesselType: v.shipCode,
        ownerCn: v.ownerCn,
        ownerRoman: v.ownerRoman,
        permitNo: v.permitNo,
        pairPermitNo: v.pairPermitNo,
        ton: v.legacy.ton,
        callSign: v.callsign ?? undefined,
        workSeaArea: v.workSeaArea ?? undefined,
        shipCode: v.shipCode,
      }));

      const ctx: MultiTrackQueryContext = {
        vessels,
        startTimeIso: fromDateTimeLocalKST(startTime),
        endTimeIso: fromDateTimeLocalKST(endTime),
      };

      const queryKey = `multi:${selected.length}:${Date.now()}`;
      useTrackQueryStore.getState().beginMultiQuery(queryKey, ctx);
      setIsQuerying(true);
      setIsOpen(false);
    },
    [selectedMmsis, startTime, endTime],
  );

  return {
    isOpen,
    open,
    reopen,
    close,
    selectedMmsis,
    toggleMmsi,
    setMmsis,
    selectAllFiltered,
    clearAll,
    searchQuery,
    setSearchQuery,
    shipCodeFilter,
    toggleShipCode,
    toggleAllShipCodes,
    onlySailing,
    setOnlySailing,
    stateFilter,
    toggleStateFilter,
    toggleAllStates,
    startTime,
    endTime,
    setStartTime,
    setEndTime,
    applyPresetDays,
    isQuerying,
    submitQuery,
    position,
    setPosition,
    selectionWarning,
    groups,
    saveGroup,
    deleteGroup,
    applyGroup,
  };
}
