import axios from 'axios';

import { useCallback, useEffect, useRef, useState } from 'react';

import { trackEvent } from '@/lib/analytics';
import { SERP_ANALYSIS_TRIGGERED } from '@/lib/event-catalog';

interface SerpAnalysisData {
  keyword: string;
  results: Array<{
    position: number;
    domain: string;
    title: string;
    description: string;
    url: string;
    word_count: number;
    heading_structure: Record<string, number>;
  }>;
  analysis: {
    avg_word_count: number;
    word_count_range: { min: number; max: number };
    common_h2_terms: string[];
    top_terms: Array<{ term: string; frequency: number }>;
  };
  nlp_terms: NlpTerm[];
  competitor_content: Array<{
    url: string;
    domain: string;
    title: string;
    word_count: number;
  }>;
}

export interface NlpTerm {
  term: string;
  term_normalized: string;
  tf_idf_score: number;
  document_frequency: number;
  avg_term_frequency: number;
  importance_rank: number;
  in_title: boolean;
  in_headings: boolean;
}

interface UseSerpAnalysisOptions {
  siteId: number;
  pollingIntervalMs?: number;
}

interface UseSerpAnalysisReturn {
  analyze: (keyword: string, languageCode?: string, targetUrl?: string) => void;
  cancel: () => void;
  serpSnapshotId: number | null;
  status: 'idle' | 'pending' | 'processing' | 'completed' | 'failed';
  error: string | null;
  isAnalyzing: boolean;
  serpData: SerpAnalysisData | null;
}

const POLLING_TIMEOUT_MS = 120_000;

export function useSerpAnalysis({
  siteId,
  pollingIntervalMs = 3000,
}: UseSerpAnalysisOptions): UseSerpAnalysisReturn {
  const [serpSnapshotId, setSerpSnapshotId] = useState<number | null>(null);
  const [status, setStatus] = useState<'idle' | 'pending' | 'processing' | 'completed' | 'failed'>(
    'idle',
  );
  const [error, setError] = useState<string | null>(null);
  const [serpData, setSerpData] = useState<SerpAnalysisData | null>(null);
  const pollingRef = useRef<NodeJS.Timeout | null>(null);
  const pollingStartRef = useRef<number>(0);

  const stopPolling = useCallback(() => {
    if (pollingRef.current) {
      clearInterval(pollingRef.current);
      pollingRef.current = null;
    }
  }, []);

  const pollStatus = useCallback(
    async (snapshotId: number) => {
      // Timeout protection — fail if polling exceeds limit
      if (
        pollingStartRef.current > 0 &&
        Date.now() - pollingStartRef.current > POLLING_TIMEOUT_MS
      ) {
        setStatus('failed');
        setError('Analysis timed out. Try again.');
        stopPolling();
        return;
      }

      try {
        const response = await axios.get(
          route('content-editor.serp-status', { site: siteId, serpSnapshot: snapshotId }),
        );

        const {
          status: newStatus,
          data,
          error: errorMsg,
        } = response.data as {
          status: string;
          data: SerpAnalysisData | null;
          error: string | null;
        };

        setStatus(newStatus as 'pending' | 'processing' | 'completed' | 'failed');

        if (newStatus === 'completed' && data) {
          setSerpData(data);
          stopPolling();
        } else if (newStatus === 'failed') {
          setError(errorMsg || 'SERP analysis failed');
          stopPolling();
        }
      } catch {
        setError('Failed to check analysis status');
        stopPolling();
      }
    },
    [siteId, stopPolling],
  );

  const cancel = useCallback(() => {
    stopPolling();
    pollingStartRef.current = 0;
    setStatus('idle');
    setError(null);
    setSerpData(null);
    setSerpSnapshotId(null);
  }, [stopPolling]);

  const analyze = useCallback(
    async (keyword: string, languageCode?: string, targetUrl?: string) => {
      // Guard against double-trigger while already analyzing
      if (pollingRef.current) {
        stopPolling();
      }

      setError(null);
      setSerpData(null);
      setStatus('pending');

      trackEvent(SERP_ANALYSIS_TRIGGERED, { keyword, site_id: String(siteId) });

      try {
        const response = await axios.post(route('content-editor.serp-analyze', { site: siteId }), {
          keyword,
          language_code: languageCode,
          target_url: targetUrl,
        });

        const { serp_snapshot_id, status: initialStatus } = response.data as {
          serp_snapshot_id: number;
          status: string;
          message: string;
        };

        setSerpSnapshotId(serp_snapshot_id);
        setStatus(initialStatus as 'pending' | 'processing' | 'completed' | 'failed');

        if (initialStatus === 'completed') {
          // Fetch full data immediately
          pollingStartRef.current = Date.now();
          await pollStatus(serp_snapshot_id);
        } else if (initialStatus === 'pending' || initialStatus === 'processing') {
          // Start polling with timeout tracking
          pollingStartRef.current = Date.now();
          pollingRef.current = setInterval(() => {
            pollStatus(serp_snapshot_id);
          }, pollingIntervalMs);
        }
      } catch (err) {
        setStatus('failed');
        if (axios.isAxiosError(err) && err.response) {
          setError(
            (err.response.data as Record<string, string>).message ||
              'Failed to start SERP analysis',
          );
        } else {
          setError('Failed to start SERP analysis');
        }
      }
    },
    [siteId, pollingIntervalMs, stopPolling, pollStatus],
  );

  // Cleanup on unmount
  useEffect(() => {
    return () => stopPolling();
  }, [stopPolling]);

  return {
    analyze,
    cancel,
    serpSnapshotId,
    status,
    error,
    isAnalyzing: status === 'pending' || status === 'processing',
    serpData,
  };
}
