import { useState, useEffect, useCallback } from 'react';
import './ReplayPage.scss';
import { getReplayWebSocketService } from '../replay/services/ReplayWebSocketService';
import useReplayStore from '../replay/stores/replayStore';
import useMergedTrackStore from '../replay/stores/mergedTrackStore';
import useAnimationStore from '../replay/stores/animationStore';
import { ConnectionState, VesselState } from '../replay/types/replay.types';
import VesselListManager from '../replay/components/VesselListManager';
import ReplayControlV2 from '../replay/components/ReplayControlV2';
import { TRACK_QUERY_MAX_DAYS, TRACK_QUERY_DEFAULT_DAYS } from '../types/constants';
import { showToast } from '../components/common/Toast';

/** 일 단위를 밀리초로 변환 */
const DAYS_TO_MS = 24 * 60 * 60 * 1000;

/** KST 기준 로컬 ISO 문자열 생성 (toISOString()은 UTC이므로 사용하지 않음) */
function toKstISOString(date) {
  const pad = (n) => String(n).padStart(2, '0');
  return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())}T${pad(date.getHours())}:${pad(date.getMinutes())}:${pad(date.getSeconds())}`;
}

/**
 * 리플레이 페이지
 * 참조: mda-react-front/src/tracking/components/ReplayV2.tsx
 */
export default function ReplayPage({ isOpen, onToggle }) {
  // 조회 기간
  const [startDate, setStartDate] = useState('');
  const [startTime, setStartTime] = useState('00:00');
  const [endDate, setEndDate] = useState('');
  const [endTime, setEndTime] = useState('23:59');

  // 조회 중 상태
  const [isQuerying, setIsQuerying] = useState(false);
  const [errorMessage, setErrorMessage] = useState('');

  // 스토어 구독
  const connectionState = useReplayStore((s) => s.connectionState);
  const queryCompleted = useReplayStore((s) => s.queryCompleted);
  const progress = useReplayStore((s) => s.progress);
  const highlightedVesselId = useReplayStore((s) => s.highlightedVesselId);
  const deletedVesselIds = useReplayStore((s) => s.deletedVesselIds);
  const selectedVesselIds = useReplayStore((s) => s.selectedVesselIds);

  const setTimeRange = useAnimationStore((s) => s.setTimeRange);

  /**
   * 선박 상태 전환 핸들러
   * DELETE: 일반/선택 → 삭제, 삭제 → 일반
   * INSERT: 일반 → 선택, 삭제 → 선택, 선택 → 일반
   */
  const handleVesselStateTransition = useCallback(
    (vesselId, action, isCurrentlyDeleted, isCurrentlySelected) => {
      let targetState;

      if (action === 'DELETE') {
        if (isCurrentlyDeleted) {
          targetState = VesselState.NORMAL;
        } else {
          targetState = VesselState.DELETED;
        }
      } else {
        // action === 'INSERT'
        if (isCurrentlyDeleted) {
          targetState = VesselState.SELECTED;
        } else if (isCurrentlySelected) {
          targetState = VesselState.NORMAL;
        } else {
          targetState = VesselState.SELECTED;
        }
      }

      useReplayStore.getState().setVesselState(vesselId, targetState);
    },
    [],
  );

  // 키보드 이벤트 리스너 (Delete/Insert 키로 항적 상태 변경)
  useEffect(() => {
    const handleKeyDown = (event) => {
      if (!highlightedVesselId) return;

      const { deletedVesselIds, selectedVesselIds } = useReplayStore.getState();
      const isCurrentlyDeleted = deletedVesselIds.has(highlightedVesselId);
      const isCurrentlySelected = selectedVesselIds.has(highlightedVesselId);

      if (event.key === 'Delete') {
        handleVesselStateTransition(highlightedVesselId, 'DELETE', isCurrentlyDeleted, isCurrentlySelected);
      } else if (event.key === 'Insert') {
        handleVesselStateTransition(highlightedVesselId, 'INSERT', isCurrentlyDeleted, isCurrentlySelected);
      }
    };

    window.addEventListener('keydown', handleKeyDown);
    return () => {
      window.removeEventListener('keydown', handleKeyDown);
    };
  }, [highlightedVesselId, handleVesselStateTransition]);

  // 조회 기간 초기화 (시작: 기본조회기간 전, 종료: 현재)
  useEffect(() => {
    const now = new Date();
    const defaultDaysAgo = new Date(now);
    defaultDaysAgo.setDate(defaultDaysAgo.getDate() - TRACK_QUERY_DEFAULT_DAYS);

    const pad = (n) => String(n).padStart(2, '0');
    setStartDate(defaultDaysAgo.toISOString().split('T')[0]);
    setStartTime('00:00');
    setEndDate(now.toISOString().split('T')[0]);
    setEndTime(`${pad(now.getHours())}:${pad(now.getMinutes())}`);
  }, []);

  // 시작일 변경 핸들러
  const handleStartDateChange = useCallback((newStartDate) => {
    setStartDate(newStartDate);

    // 현재 종료일/시간과 비교
    const start = new Date(`${newStartDate}T${startTime}:00`);
    const end = new Date(`${endDate}T${endTime}:00`);
    const diffDays = (end - start) / DAYS_TO_MS;
    const pad = (n) => String(n).padStart(2, '0');

    // 시작일이 종료일보다 뒤인 경우 → 종료일을 시작일 + 기본조회기간으로 조정
    if (diffDays < 0) {
      const adjustedEnd = new Date(start.getTime() + TRACK_QUERY_DEFAULT_DAYS * DAYS_TO_MS);
      setEndDate(adjustedEnd.toISOString().split('T')[0]);
      setEndTime(`${pad(adjustedEnd.getHours())}:${pad(adjustedEnd.getMinutes())}`);
      showToast(`종료일이 시작일보다 앞서 기본 조회기간 ${TRACK_QUERY_DEFAULT_DAYS}일로 자동 설정됩니다.`);
    }
    // 최대 조회기간 초과 시 종료일 자동 조정
    else if (diffDays > TRACK_QUERY_MAX_DAYS) {
      const adjustedEnd = new Date(start.getTime() + TRACK_QUERY_MAX_DAYS * DAYS_TO_MS);
      setEndDate(adjustedEnd.toISOString().split('T')[0]);
      setEndTime(`${pad(adjustedEnd.getHours())}:${pad(adjustedEnd.getMinutes())}`);
      showToast(`최대 조회기간 ${TRACK_QUERY_MAX_DAYS}일로 자동 설정됩니다.`);
    }
  }, [startTime, endDate, endTime]);

  // 종료일 변경 핸들러
  const handleEndDateChange = useCallback((newEndDate) => {
    setEndDate(newEndDate);

    // 현재 시작일/시간과 비교
    const start = new Date(`${startDate}T${startTime}:00`);
    const end = new Date(`${newEndDate}T${endTime}:00`);
    const diffDays = (end - start) / DAYS_TO_MS;
    const pad = (n) => String(n).padStart(2, '0');

    // 종료일이 시작일보다 앞인 경우 → 시작일을 종료일 - 기본조회기간으로 조정
    if (diffDays < 0) {
      const adjustedStart = new Date(end.getTime() - TRACK_QUERY_DEFAULT_DAYS * DAYS_TO_MS);
      setStartDate(adjustedStart.toISOString().split('T')[0]);
      setStartTime(`${pad(adjustedStart.getHours())}:${pad(adjustedStart.getMinutes())}`);
      showToast(`시작일이 종료일보다 뒤서 기본 조회기간 ${TRACK_QUERY_DEFAULT_DAYS}일로 자동 설정됩니다.`);
    }
    // 최대 조회기간 초과 시 시작일 자동 조정
    else if (diffDays > TRACK_QUERY_MAX_DAYS) {
      const adjustedStart = new Date(end.getTime() - TRACK_QUERY_MAX_DAYS * DAYS_TO_MS);
      setStartDate(adjustedStart.toISOString().split('T')[0]);
      setStartTime(`${pad(adjustedStart.getHours())}:${pad(adjustedStart.getMinutes())}`);
      showToast(`최대 조회기간 ${TRACK_QUERY_MAX_DAYS}일로 자동 설정됩니다.`);
    }
  }, [startDate, startTime, endTime]);

  // 쿼리 완료 감지
  useEffect(() => {
    if (queryCompleted) {
      setIsQuerying(false);
    }
  }, [queryCompleted]);

  // 연결 에러 감지
  useEffect(() => {
    if (connectionState === ConnectionState.ERROR && isQuerying) {
      setIsQuerying(false);
      setErrorMessage('연결 오류가 발생했습니다.');
    }
  }, [connectionState, isQuerying]);

  // 컴포넌트 언마운트 시 정리
  useEffect(() => {
    return () => {
      getReplayWebSocketService().disconnect();
    };
  }, []);

  /**
   * 조회 실행
   */
  const handleQuery = useCallback(async () => {
    if (!startDate || !endDate) {
      showToast('조회 기간을 입력해주세요.');
      return;
    }

    // 시작/종료 시간 조합 (KST 기준)
    const from = new Date(`${startDate}T${startTime}:00`);
    const to = new Date(`${endDate}T${endTime}:00`);

    if (isNaN(from.getTime()) || isNaN(to.getTime())) {
      showToast('올바른 날짜/시간을 입력해주세요.');
      return;
    }

    if (from >= to) {
      showToast('종료 시간은 시작 시간보다 이후여야 합니다.');
      return;
    }

    try {
      setIsQuerying(true);
      setErrorMessage('');

      // 시간 범위 설정 (애니메이션 스토어)
      setTimeRange(from.getTime(), to.getTime());

      // WebSocket 쿼리 실행
      const wsService = getReplayWebSocketService();
      await wsService.executeQuery({
        startTime: toKstISOString(from),
        endTime: toKstISOString(to),
      });
    } catch (error) {
      console.error('[ReplayPage] 쿼리 실패:', error);
      setIsQuerying(false);
      setErrorMessage(`조회 실패: ${error.message}`);
    }
  }, [startDate, startTime, endDate, endTime, setTimeRange]);

  /**
   * 조회 취소
   */
  const handleCancel = useCallback(() => {
    getReplayWebSocketService().cancelQuery();
    setIsQuerying(false);
  }, []);

  return (
    <aside className={`slidePanel replay-panel ${isOpen ? '' : 'is-closed'}`}>
      {/* 토글 버튼 */}
      <button
        type="button"
        className="toogle"
        onClick={onToggle}
        aria-label="패널 토글"
      >
        <span className="blind">패널 토글</span>
      </button>

      {/* 헤더 */}
      <div className="panelHeader">
        <h2 className="panelTitle">리플레이</h2>
      </div>

      {/* 본문 */}
      <div className="panelBody">
        {/* 조회 조건 */}
        <div className="query-section">
          <h3 className="section-title">조회 기간</h3>

          {/* 시작 시간 */}
          <div className="query-row">
            <label htmlFor="replay-start-date" className="query-label">시작</label>
            <div className="datetime-inputs">
              <input
                id="replay-start-date"
                type="date"
                value={startDate}
                onChange={(e) => handleStartDateChange(e.target.value)}
                disabled={isQuerying}
                className="input-date"
              />
              <input
                id="replay-start-time"
                type="time"
                value={startTime}
                onChange={(e) => setStartTime(e.target.value)}
                disabled={isQuerying}
                className="input-time"
              />
            </div>
          </div>

          {/* 종료 시간 */}
          <div className="query-row">
            <label htmlFor="replay-end-date" className="query-label">종료</label>
            <div className="datetime-inputs">
              <input
                id="replay-end-date"
                type="date"
                value={endDate}
                onChange={(e) => handleEndDateChange(e.target.value)}
                disabled={isQuerying}
                className="input-date"
              />
              <input
                id="replay-end-time"
                type="time"
                value={endTime}
                onChange={(e) => setEndTime(e.target.value)}
                disabled={isQuerying}
                className="input-time"
              />
            </div>
          </div>

          {/* 버튼 */}
          <div className="btnBox">
            {isQuerying ? (
              <button
                type="button"
                className="btn btn-cancel btn-query"
                onClick={handleCancel}
              >
                취소
              </button>
            ) : (
              <button
                type="button"
                className="btn btn-primary btn-query"
                onClick={handleQuery}
              >
                조회
              </button>
            )}
          </div>
        </div>

        {/* 조회 결과 영역 */}
        <div className="result-section">
          {errorMessage && (
            <div className="error-message">{errorMessage}</div>
          )}
          {connectionState === ConnectionState.CONNECTING && (
            <div className="loading-message">서버 연결 중...</div>
          )}
          {isQuerying && connectionState === ConnectionState.CONNECTED && (
            <div className="loading-message">
              <div>데이터를 불러오는 중입니다...</div>
              {progress > 0 && (
                <div className="progress-info">{Math.min(progress, 100).toFixed(0)}% 완료</div>
              )}
            </div>
          )}
          {queryCompleted && (
            <>
              {/* 필터 컨트롤 (선종, 선박목록, 항적, 라벨) */}
              <ReplayControlV2 />
              {/* 선박 분류 관리 패널 */}
              <VesselListManager className="vessel-list-manager-replay" />
            </>
          )}
          {!isQuerying && !queryCompleted && !errorMessage && connectionState !== ConnectionState.CONNECTING && (
            <div className="empty-message">
              조회 버튼을 클릭하여 리플레이를 시작하세요.
            </div>
          )}
        </div>
      </div>
    </aside>
  );
}
