import { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState, type ReactNode } from 'react';
import { toast } from 'sonner';

import {
  isAutomationUnauthorizedError,
  fetchSearchManualInterventions,
  openSearchManualIntervention,
  type SearchManualInterventionAlert,
} from '@/services/automationService';
import { useAuth } from '@/hooks/useAuth';
import {
  DEFAULT_MANUAL_INTERVENTION_ALERT_SOUND_ID,
  getManualInterventionAlertSoundOption,
  MANUAL_INTERVENTION_ALERT_SOUND_STORAGE_KEY,
  manualInterventionAlertSoundOptions,
  normalizeManualInterventionAlertSoundId,
  playAlertSound,
  type ManualInterventionAlertSoundOption,
} from '@/lib/manualInterventionAlertSounds';

const POLL_INTERVAL_MS = 2000;

type SearchManualInterventionContextValue = {
  alerts: SearchManualInterventionAlert[];
  activeCount: number;
  latestAlert: SearchManualInterventionAlert | null;
  openingTaskId: string | null;
  selectedSoundId: string;
  selectedSound: ManualInterventionAlertSoundOption;
  soundOptions: ManualInterventionAlertSoundOption[];
  refresh: () => Promise<void>;
  openAlert: (alert: SearchManualInterventionAlert) => Promise<void>;
  setSelectedSoundId: (soundId: string) => void;
  previewSelectedSound: () => Promise<void>;
};

const SearchManualInterventionContext = createContext<SearchManualInterventionContextValue | null>(null);

function readStoredSelectedSoundId() {
  if (typeof window === 'undefined' || typeof window.localStorage?.getItem !== 'function') {
    return DEFAULT_MANUAL_INTERVENTION_ALERT_SOUND_ID;
  }

  const storedValue = window.localStorage.getItem(MANUAL_INTERVENTION_ALERT_SOUND_STORAGE_KEY);
  return normalizeManualInterventionAlertSoundId(storedValue);
}

function sortAlerts(alerts: SearchManualInterventionAlert[]) {
  return [...alerts].sort((left, right) => {
    const rightTime = Date.parse(right.updatedAt || right.detectedAt || '') || 0;
    const leftTime = Date.parse(left.updatedAt || left.detectedAt || '') || 0;
    return rightTime - leftTime;
  });
}

export function SearchManualInterventionProvider({ children }: { children: ReactNode }) {
  const { isAuthenticated, isBootstrapping, session } = useAuth();
  const [alerts, setAlerts] = useState<SearchManualInterventionAlert[]>([]);
  const [openingTaskId, setOpeningTaskId] = useState<string | null>(null);
  const [selectedSoundId, setSelectedSoundIdState] = useState(readStoredSelectedSoundId);
  const [pollingPausedForAuthError, setPollingPausedForAuthError] = useState(false);
  const audioRef = useRef<HTMLAudioElement | null>(null);
  const lastAlertSignatureRef = useRef('');
  const sessionToken = session?.token ?? '';
  const canPoll = !isBootstrapping && isAuthenticated && Boolean(sessionToken);

  const loadAlerts = useCallback(async () => {
    if (!canPoll || pollingPausedForAuthError) {
      setAlerts([]);
      return;
    }

    try {
      const next = await fetchSearchManualInterventions();
      setAlerts(sortAlerts(next.alerts.filter((alert) => alert.active !== false)));
    } catch (error) {
      setAlerts([]);
      if (isAutomationUnauthorizedError(error)) {
        setPollingPausedForAuthError(true);
      }
    }
  }, [canPoll, pollingPausedForAuthError]);

  useEffect(() => {
    setPollingPausedForAuthError(false);
    if (!canPoll) {
      setAlerts([]);
      lastAlertSignatureRef.current = '';
    }
  }, [canPoll, sessionToken]);

  useEffect(() => {
    if (!canPoll || pollingPausedForAuthError) {
      return undefined;
    }

    void loadAlerts();
    const timer = window.setInterval(() => {
      void loadAlerts();
    }, POLL_INTERVAL_MS);

    return () => {
      window.clearInterval(timer);
    };
  }, [canPoll, loadAlerts, pollingPausedForAuthError]);

  const activeCount = alerts.length;
  const latestAlert = alerts[0] ?? null;
  const selectedSound = getManualInterventionAlertSoundOption(selectedSoundId);
  const alertSignature = alerts.map((alert) => `${alert.alertId}:${alert.updatedAt}:${alert.message}`).join('|');

  const setSelectedSoundId = useCallback((soundId: string) => {
    const nextSoundId = normalizeManualInterventionAlertSoundId(soundId);
    setSelectedSoundIdState(nextSoundId);
  }, []);

  useEffect(() => {
    if (typeof window === 'undefined' || typeof window.localStorage?.setItem !== 'function') {
      return;
    }

    window.localStorage.setItem(MANUAL_INTERVENTION_ALERT_SOUND_STORAGE_KEY, selectedSoundId);
  }, [selectedSoundId]);

  const previewSelectedSound = useCallback(async () => {
    await playAlertSound(audioRef, selectedSound);
  }, [selectedSound]);

  useEffect(() => {
    if (!alertSignature || lastAlertSignatureRef.current === alertSignature) {
      return;
    }

    lastAlertSignatureRef.current = alertSignature;
    void playAlertSound(audioRef, selectedSound);
    if (latestAlert) {
      toast.error(latestAlert.message, {
        duration: 7000,
        position: 'bottom-right',
      });
    }
  }, [alertSignature, latestAlert, selectedSound]);

  const openAlert = useCallback(async (alert: SearchManualInterventionAlert) => {
    setOpeningTaskId(alert.taskId);
    try {
      const response = await openSearchManualIntervention(alert.taskId);
      toast.success(response.message, {
        duration: 5000,
        position: 'bottom-right',
      });
      await loadAlerts();
    } catch (error) {
      if (isAutomationUnauthorizedError(error)) {
        setAlerts([]);
        setPollingPausedForAuthError(true);
      }

      const message = isAutomationUnauthorizedError(error)
        ? `登录态已失效，请重新登录：${error.message}`
        : `打开验证码会话失败: ${error instanceof Error ? error.message : String(error)}`;

      toast.error(message, {
        duration: 6000,
        position: 'bottom-right',
      });
      throw error;
    } finally {
      setOpeningTaskId(null);
    }
  }, [loadAlerts]);

  const value = useMemo<SearchManualInterventionContextValue>(() => ({
    alerts,
    activeCount,
    latestAlert,
    openingTaskId,
    selectedSoundId,
    selectedSound,
    soundOptions: manualInterventionAlertSoundOptions,
    refresh: loadAlerts,
    openAlert,
    setSelectedSoundId,
    previewSelectedSound,
  }), [activeCount, alerts, latestAlert, loadAlerts, openAlert, openingTaskId, previewSelectedSound, selectedSound, selectedSoundId, setSelectedSoundId]);

  return (
    <SearchManualInterventionContext.Provider value={value}>
      {children}
    </SearchManualInterventionContext.Provider>
  );
}

// eslint-disable-next-line react-refresh/only-export-components
export function useSearchManualIntervention() {
  const context = useContext(SearchManualInterventionContext);
  if (!context) {
    throw new Error('useSearchManualIntervention 必须在 SearchManualInterventionProvider 内使用');
  }
  return context;
}
