import { useMemo, useEffect, useCallback, useState, useRef, type CSSProperties } from 'react';
import type { VesselSelectModalState } from '../../features/vesselSelect/hooks/useVesselSelectModal';
import type { DerivedLegacyVessel } from '../../features/legacyDashboard/model/types';
import { VESSEL_TYPE_ORDER, VESSEL_TYPES } from '../../entities/vessel/model/meta';
import { MAX_VESSEL_GROUPS } from '../../features/vesselSelect/model/types';
import { VesselSelectGrid } from './VesselSelectGrid';
import { ToggleButton, TextInput, Button } from '@wing/ui';

export type SortKey = 'shipCode' | 'permitNo' | 'name' | 'mmsi' | 'sog' | 'state';
export type SortDir = 'asc' | 'desc';

interface VesselSelectModalProps {
  modal: VesselSelectModalState;
  vessels: DerivedLegacyVessel[];
}

const STRIP_RE = /[\s\-.,_]/g;

function normalize(s: string): string {
  return s.replace(STRIP_RE, '').toLowerCase();
}

function matchesQuery(v: DerivedLegacyVessel, nq: string): boolean {
  if (normalize(v.permitNo).includes(nq)) return true;
  if (normalize(v.name).includes(nq)) return true;
  if (v.legacy.shipNameRoman && normalize(v.legacy.shipNameRoman).includes(nq)) return true;
  if (v.legacy.shipNameCn && normalize(v.legacy.shipNameCn).includes(nq)) return true;
  if (normalize(String(v.mmsi)).includes(nq)) return true;
  return false;
}

const STATE_LABELS = ['조업', '항해', '정지', '저속', '미상'] as const;
const STATE_COLORS: Record<string, string> = {
  조업: '#22C55E',
  항해: '#3B82F6',
  정지: '#64748B',
  저속: '#EAB308',
  미상: '#6B7280',
};

const STYLE_OVERLAY: CSSProperties = {
  position: 'fixed',
  inset: 0,
  zIndex: 1050,
  display: 'flex',
  alignItems: 'center',
  justifyContent: 'center',
  pointerEvents: 'none',
};

const STYLE_BACKDROP: CSSProperties = {
  position: 'fixed',
  inset: 0,
  background: 'rgba(0,0,0,0.35)',
  pointerEvents: 'auto',
};

const STYLE_CONTENT: CSSProperties = {
  position: 'relative',
  display: 'flex',
  flexDirection: 'column',
  maxWidth: 720,
  width: '95vw',
  maxHeight: '57vh',
  background: 'rgba(15,23,42,0.96)',
  backdropFilter: 'blur(12px)',
  border: '1px solid rgba(148,163,184,0.25)',
  borderRadius: 12,
  color: '#e2e8f0',
  overflow: 'hidden',
  pointerEvents: 'auto',
};

const STYLE_HEADER: CSSProperties = {
  display: 'flex',
  alignItems: 'center',
  justifyContent: 'space-between',
  padding: '10px 16px',
  borderBottom: '1px solid rgba(148,163,184,0.15)',
  flexShrink: 0,
  cursor: 'grab',
  userSelect: 'none',
};

const STYLE_CLOSE_BTN: CSSProperties = {
  background: 'transparent',
  border: 'none',
  color: '#94a3b8',
  cursor: 'pointer',
  fontSize: 16,
  lineHeight: 1,
  padding: '2px 6px',
};

const STYLE_FILTERS: CSSProperties = {
  display: 'flex',
  flexDirection: 'column',
  gap: 6,
  padding: '8px 16px',
  borderBottom: '1px solid rgba(148,163,184,0.1)',
  flexShrink: 0,
};

const STYLE_FILTER_ROW: CSSProperties = {
  display: 'flex',
  alignItems: 'center',
  flexWrap: 'wrap',
  gap: 5,
};

const STYLE_FILTER_LABEL: CSSProperties = {
  fontSize: 11,
  color: '#64748b',
  minWidth: 28,
  flexShrink: 0,
};

const STYLE_DOT = (color: string): CSSProperties => ({
  display: 'inline-block',
  width: 7,
  height: 7,
  borderRadius: '50%',
  background: color,
  marginRight: 3,
  verticalAlign: 'middle',
});

const STYLE_GROUP_BAR: CSSProperties = {
  display: 'flex',
  alignItems: 'center',
  gap: 6,
  padding: '6px 16px',
  borderBottom: '1px solid rgba(148,163,184,0.1)',
  flexShrink: 0,
  overflowX: 'auto',
};

const STYLE_GROUP_BTN: CSSProperties = {
  display: 'inline-flex',
  alignItems: 'center',
  gap: 4,
  padding: '3px 8px',
  fontSize: 11,
  borderRadius: 4,
  border: '1px solid rgba(148,163,184,0.3)',
  background: 'rgba(30,41,59,0.6)',
  color: '#cbd5e1',
  cursor: 'pointer',
  whiteSpace: 'nowrap',
  flexShrink: 0,
};

const STYLE_GROUP_DELETE: CSSProperties = {
  fontSize: 9,
  color: '#94a3b8',
  cursor: 'pointer',
  padding: '0 2px',
  lineHeight: 1,
};

const STYLE_GROUP_INPUT: CSSProperties = {
  fontSize: 11,
  padding: '3px 6px',
  borderRadius: 4,
  border: '1px solid rgba(59,130,246,0.5)',
  background: 'rgba(30,41,59,0.8)',
  color: '#e2e8f0',
  outline: 'none',
  width: 100,
};

const STYLE_SEARCH: CSSProperties = {
  padding: '6px 16px',
  borderBottom: '1px solid rgba(148,163,184,0.1)',
  flexShrink: 0,
};

const STYLE_GRID: CSSProperties = {
  flex: 1,
  overflowY: 'auto',
  minHeight: 0,
};

const STYLE_DATE_BAR: CSSProperties = {
  display: 'flex',
  alignItems: 'center',
  flexWrap: 'wrap',
  gap: 6,
  padding: '8px 16px',
  borderTop: '1px solid rgba(148,163,184,0.1)',
  flexShrink: 0,
  fontSize: 11,
};

const STYLE_DATETIME_INPUT: CSSProperties = {
  fontSize: 11,
  padding: '3px 6px',
  borderRadius: 4,
  border: '1px solid rgba(148,163,184,0.35)',
  background: 'rgba(30,41,59,0.8)',
  color: '#e2e8f0',
  colorScheme: 'dark',
};

const STYLE_FOOTER: CSSProperties = {
  display: 'flex',
  alignItems: 'center',
  gap: 10,
  padding: '8px 16px',
  borderTop: '1px solid rgba(148,163,184,0.15)',
  flexShrink: 0,
};

const STYLE_FOOTER_SPACER: CSSProperties = { flex: 1 };

const STYLE_SEPARATOR: CSSProperties = {
  width: 1,
  height: 14,
  background: 'rgba(148,163,184,0.2)',
  flexShrink: 0,
};

export function VesselSelectModal({ modal, vessels }: VesselSelectModalProps) {
  const {
    isOpen,
    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,
  } = modal;

  // ── 그룹 저장 입력 ──
  const [isSavingGroup, setIsSavingGroup] = useState(false);
  const [groupNameDraft, setGroupNameDraft] = useState('');
  const [groupWarning, setGroupWarning] = useState<string | null>(null);
  const groupInputRef = useRef<HTMLInputElement>(null);

  const handleSaveGroup = useCallback(() => {
    if (!groupNameDraft.trim()) {
      setIsSavingGroup(false);
      return;
    }
    const warn = saveGroup(groupNameDraft, [...selectedMmsis]);
    if (warn) {
      setGroupWarning(warn);
    } else {
      setGroupWarning(null);
    }
    setIsSavingGroup(false);
    setGroupNameDraft('');
  }, [groupNameDraft, saveGroup, selectedMmsis]);

  // ── 정렬 ──
  const [sortKey, setSortKey] = useState<SortKey | null>(null);
  const [sortDir, setSortDir] = useState<SortDir>('asc');

  const handleSort = useCallback((key: SortKey) => {
    setSortKey((prev) => {
      if (prev === key) {
        setSortDir((d) => (d === 'asc' ? 'desc' : 'asc'));
        return key;
      }
      setSortDir('asc');
      return key;
    });
  }, []);

  // ── 필터 ──
  const filteredVessels = useMemo(() => {
    let list = vessels;
    if (shipCodeFilter.size > 0) {
      list = list.filter((v) => shipCodeFilter.has(v.shipCode));
    }
    if (stateFilter.size > 0) {
      list = list.filter((v) => stateFilter.has(v.state.label));
    }
    if (onlySailing) {
      list = list.filter((v) => v.state.isFishing || v.state.isTransit);
    }
    const nq = searchQuery.length >= 2 ? normalize(searchQuery) : '';
    if (nq) {
      list = list.filter((v) => matchesQuery(v, nq));
    }
    return list;
  }, [vessels, shipCodeFilter, stateFilter, onlySailing, searchQuery]);

  const sortedVessels = useMemo(() => {
    if (!sortKey) return filteredVessels;
    const arr = [...filteredVessels];
    arr.sort((a, b) => {
      let cmp = 0;
      switch (sortKey) {
        case 'shipCode': cmp = a.shipCode.localeCompare(b.shipCode); break;
        case 'permitNo': cmp = a.permitNo.localeCompare(b.permitNo); break;
        case 'name':     cmp = a.name.localeCompare(b.name, 'ko'); break;
        case 'mmsi':     cmp = a.mmsi - b.mmsi; break;
        case 'sog':      cmp = (a.sog ?? -1) - (b.sog ?? -1); break;
        case 'state':    cmp = a.state.label.localeCompare(b.state.label, 'ko'); break;
      }
      return sortDir === 'asc' ? cmp : -cmp;
    });
    return arr;
  }, [filteredVessels, sortKey, sortDir]);

  // ── Escape 닫기 ──
  const handleKeyDown = useCallback(
    (e: KeyboardEvent) => {
      if (e.key === 'Escape') close();
    },
    [close],
  );

  useEffect(() => {
    if (!isOpen) return;
    document.addEventListener('keydown', handleKeyDown);
    return () => document.removeEventListener('keydown', handleKeyDown);
  }, [isOpen, handleKeyDown]);

  // ── 드래그 ──
  const handlePointerDown = useCallback(
    (e: React.PointerEvent) => {
      if ((e.target as HTMLElement).closest('button')) return;
      e.preventDefault();
      const startX = e.clientX - position.x;
      const startY = e.clientY - position.y;
      document.body.style.cursor = 'grabbing';

      const handleMove = (ev: PointerEvent) => {
        setPosition({ x: ev.clientX - startX, y: ev.clientY - startY });
      };
      const handleUp = () => {
        document.body.style.cursor = '';
        document.removeEventListener('pointermove', handleMove);
        document.removeEventListener('pointerup', handleUp);
      };
      document.addEventListener('pointermove', handleMove);
      document.addEventListener('pointerup', handleUp);
    },
    [position, setPosition],
  );

  // ── 전체 선택 ──
  const isAllSelected = filteredVessels.length > 0 && filteredVessels.every((v) => selectedMmsis.has(v.mmsi));

  const handleSelectAllChange = useCallback(() => {
    if (isAllSelected) clearAll();
    else selectAllFiltered(filteredVessels);
  }, [isAllSelected, clearAll, selectAllFiltered, filteredVessels]);

  const handleContentClick = useCallback((e: React.MouseEvent) => {
    e.stopPropagation();
  }, []);

  if (!isOpen) return null;

  return (
    <>
      <div style={STYLE_BACKDROP} onClick={close} />
      <div
        style={{
          ...STYLE_OVERLAY,
        }}
      >
        <div
          style={{
            ...STYLE_CONTENT,
            transform: `translate(${position.x}px, ${position.y}px)`,
          }}
          onClick={handleContentClick}
        >
          {/* 헤더 (드래그 핸들) */}
          <div
            style={STYLE_HEADER}
            onPointerDown={handlePointerDown}
          >
            <div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
              <span style={{ color: '#64748b', fontSize: 12 }}>≡</span>
              <strong style={{ fontSize: 13 }}>대상 선박 선택</strong>
              <span style={{ color: '#64748b', fontSize: 11 }}>({vessels.length}척)</span>
            </div>
            <button style={STYLE_CLOSE_BTN} onClick={close}>
              ✕
            </button>
          </div>

          {/* 업종 + 상태 필터 */}
          <div style={STYLE_FILTERS}>
            <div style={STYLE_FILTER_ROW}>
              <span style={STYLE_FILTER_LABEL}>업종</span>
              <ToggleButton on={shipCodeFilter.size === VESSEL_TYPE_ORDER.length} onClick={() => toggleAllShipCodes(VESSEL_TYPE_ORDER)}>
                전체
              </ToggleButton>
              {VESSEL_TYPE_ORDER.map((code) => {
                const meta = VESSEL_TYPES[code];
                return (
                  <ToggleButton key={code} on={shipCodeFilter.has(code)} onClick={() => toggleShipCode(code)}>
                    <span style={STYLE_DOT(meta.color)} />
                    {code}
                  </ToggleButton>
                );
              })}
            </div>
            <div style={STYLE_FILTER_ROW}>
              <span style={STYLE_FILTER_LABEL}>상태</span>
              <ToggleButton on={stateFilter.size === STATE_LABELS.length} onClick={() => toggleAllStates([...STATE_LABELS])}>
                전체
              </ToggleButton>
              {STATE_LABELS.map((label) => (
                <ToggleButton key={label} on={stateFilter.has(label)} onClick={() => toggleStateFilter(label)}>
                  <span style={STYLE_DOT(STATE_COLORS[label])} />
                  {label}
                </ToggleButton>
              ))}
              <label
                style={{
                  display: 'flex',
                  alignItems: 'center',
                  gap: 4,
                  fontSize: 11,
                  color: '#94a3b8',
                  cursor: 'pointer',
                  marginLeft: 4,
                }}
              >
                <input
                  type="checkbox"
                  checked={onlySailing}
                  onChange={(e) => setOnlySailing(e.target.checked)}
                  style={{ cursor: 'pointer' }}
                />
                운항중
              </label>
            </div>
          </div>

          {/* 그룹 바 */}
          {(groups.length > 0 || selectedMmsis.size > 0) && (
            <div style={STYLE_GROUP_BAR}>
              {isSavingGroup ? (
                <input
                  ref={groupInputRef}
                  style={STYLE_GROUP_INPUT}
                  placeholder="그룹명 입력"
                  value={groupNameDraft}
                  onChange={(e) => setGroupNameDraft(e.target.value)}
                  onKeyDown={(e) => {
                    if (e.key === 'Enter') handleSaveGroup();
                    if (e.key === 'Escape') { setIsSavingGroup(false); setGroupNameDraft(''); }
                  }}
                  onBlur={handleSaveGroup}
                  autoFocus
                />
              ) : (
                <Button
                  variant="ghost"
                  size="sm"
                  disabled={selectedMmsis.size === 0 || (groups.length >= MAX_VESSEL_GROUPS && !groups.some((g) => g.mmsis.length === selectedMmsis.size))}
                  title={groups.length >= MAX_VESSEL_GROUPS ? `최대 ${MAX_VESSEL_GROUPS}개` : undefined}
                  onClick={() => { setIsSavingGroup(true); setGroupWarning(null); }}
                >
                  그룹 저장
                </Button>
              )}
              {groupWarning && <span style={{ color: '#fca5a5', fontSize: 10 }}>{groupWarning}</span>}
              {groups.map((g) => (
                <button
                  type="button"
                  key={g.id}
                  style={STYLE_GROUP_BTN}
                  onClick={() => applyGroup(g)}
                  title={`${g.mmsis.length}척`}
                >
                  {g.name}
                  <span
                    style={STYLE_GROUP_DELETE}
                    onClick={(e) => { e.stopPropagation(); deleteGroup(g.id); }}
                    title="삭제"
                  >
                    ✕
                  </span>
                </button>
              ))}
            </div>
          )}

          {/* 검색 */}
          <div style={STYLE_SEARCH}>
            <TextInput placeholder="검색: 등록번호 / 선박명 / MMSI" value={searchQuery} onChange={(e) => setSearchQuery(e.target.value)} />
          </div>

          {/* 그리드 */}
          <div style={STYLE_GRID}>
            <VesselSelectGrid
              vessels={sortedVessels}
              selectedMmsis={selectedMmsis}
              toggleMmsi={toggleMmsi}
              setMmsis={setMmsis}
              sortKey={sortKey}
              sortDir={sortDir}
              onSort={handleSort}
            />
          </div>

          {/* 기간 설정 바 */}
          <div style={STYLE_DATE_BAR}>
            {[7, 14, 21, 28].map((d) => (
              <Button key={d} variant="ghost" size="sm" onClick={() => applyPresetDays(d)}>
                {d}일
              </Button>
            ))}
            <div style={STYLE_SEPARATOR} />
            <label style={{ color: '#94a3b8', display: 'flex', alignItems: 'center', gap: 4 }}>
              시작
              <input type="datetime-local" value={startTime} onChange={(e) => setStartTime(e.target.value)} style={STYLE_DATETIME_INPUT} />
            </label>
            <label style={{ color: '#94a3b8', display: 'flex', alignItems: 'center', gap: 4 }}>
              종료
              <input type="datetime-local" value={endTime} onChange={(e) => setEndTime(e.target.value)} style={STYLE_DATETIME_INPUT} />
            </label>
          </div>

          {/* 푸터 */}
          <div style={STYLE_FOOTER}>
            <label
              style={{
                display: 'flex',
                alignItems: 'center',
                gap: 4,
                fontSize: 11,
                color: '#cbd5e1',
                cursor: 'pointer',
              }}
            >
              <input type="checkbox" checked={isAllSelected} onChange={handleSelectAllChange} style={{ cursor: 'pointer' }} />
              전체 선택 ({filteredVessels.length}척)
            </label>
            <Button variant="ghost" size="sm" disabled={selectedMmsis.size === 0} onClick={clearAll}>
              초기화
            </Button>
            {selectionWarning && <span style={{ color: '#fca5a5', fontSize: 11 }}>{selectionWarning}</span>}
            <div style={STYLE_FOOTER_SPACER} />
            <span style={{ color: '#93c5fd', fontSize: 12 }}>선택 {selectedMmsis.size}척</span>
            <Button variant="primary" size="md" disabled={selectedMmsis.size === 0} onClick={() => submitQuery(vessels)}>
              {isQuerying ? '재조회' : '조회 시작'}
            </Button>
          </div>
        </div>
      </div>
    </>
  );
}
