import axios from 'axios';

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

import type { NlpTerm } from './useSerpAnalysis';

export interface TermStatus {
  term: string;
  importance_rank: number;
  tf_idf_score: number;
  present: boolean;
  frequency: number;
  competitor_avg_frequency: number;
  in_title: boolean;
  in_headings: boolean;
  status: 'covered' | 'underused' | 'missing';
}

interface ContentScoreResult {
  overall_score: number;
  term_coverage: {
    score: number;
    covered: number;
    total: number;
    percentage: number;
  };
  word_count_score: {
    score: number;
    draft_count: number;
    competitor_avg: number;
    competitor_median: number;
  };
  structure_score: {
    score: number;
    details: Record<string, unknown>;
  };
  readability_score: {
    score: number;
    details: Record<string, unknown>;
  };
  terms: TermStatus[];
}

interface UseContentScoreOptions {
  content: string;
  siteId: number;
  siteUrl: string;
  serpSnapshotId: number | null;
  nlpTerms: NlpTerm[] | null;
  debounceMs?: number;
}

interface UseContentScoreReturn {
  score: ContentScoreResult | null;
  isLoading: boolean;
  error: string | null;
  terms: TermStatus[];
}

/**
 * Quick client-side term matching for instant feedback.
 */
function matchTermsLocally(content: string, nlpTerms: NlpTerm[]): TermStatus[] {
  const lowerContent = content.toLowerCase().replace(/<[^>]*>/g, ' ');

  return nlpTerms.map((term) => {
    const normalizedTerm = term.term_normalized.toLowerCase();
    const regex = new RegExp(normalizedTerm.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'), 'gi');
    const matches = lowerContent.match(regex);
    const frequency = matches?.length ?? 0;
    const present = frequency > 0;

    let status: 'covered' | 'underused' | 'missing' = 'missing';
    if (present) {
      const words = lowerContent.split(/\s+/).filter(Boolean);
      const wordCount = Math.max(words.length, 1);
      const relativeFreq = frequency / wordCount;
      status = relativeFreq >= term.avg_term_frequency * 0.5 ? 'covered' : 'underused';
    }

    return {
      term: term.term,
      importance_rank: term.importance_rank,
      tf_idf_score: term.tf_idf_score,
      present,
      frequency,
      competitor_avg_frequency: term.avg_term_frequency,
      in_title: term.in_title,
      in_headings: term.in_headings,
      status,
    };
  });
}

export function useContentScore({
  content,
  siteId,
  siteUrl,
  serpSnapshotId,
  nlpTerms,
  debounceMs = 2000,
}: UseContentScoreOptions): UseContentScoreReturn {
  const [score, setScore] = useState<ContentScoreResult | null>(null);
  const [isLoading, setIsLoading] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const abortControllerRef = useRef<AbortController | null>(null);
  const debounceTimerRef = useRef<NodeJS.Timeout | null>(null);

  // Client-side term matching for instant feedback
  const localTerms = useMemo(() => {
    if (!nlpTerms || nlpTerms.length === 0 || !content.trim()) return [];
    return matchTermsLocally(content, nlpTerms);
  }, [content, nlpTerms]);

  // Server-side scoring (debounced)
  useEffect(() => {
    if (debounceTimerRef.current) {
      clearTimeout(debounceTimerRef.current);
    }

    if (abortControllerRef.current) {
      abortControllerRef.current.abort();
    }

    if (!serpSnapshotId || !content.trim()) {
      return;
    }

    setIsLoading(true);
    setError(null);

    debounceTimerRef.current = setTimeout(() => {
      const abortController = new AbortController();
      abortControllerRef.current = abortController;

      const fetchScore = async () => {
        try {
          const response = await axios.post<ContentScoreResult>(
            route('content-editor.score', { site: siteId }),
            {
              content,
              serp_snapshot_id: serpSnapshotId,
              site_url: siteUrl,
            },
            { signal: abortController.signal },
          );

          if (!abortController.signal.aborted) {
            setScore(response.data);
            setIsLoading(false);
            setError(null);
          }
        } catch (err) {
          if (!abortController.signal.aborted) {
            setIsLoading(false);
            if (axios.isAxiosError(err) && err.response) {
              setError(
                (err.response.data as Record<string, string>).message || 'Failed to score content',
              );
            } else {
              setError('Failed to score content');
            }
          }
        }
      };

      fetchScore();
    }, debounceMs);

    return () => {
      if (debounceTimerRef.current) {
        clearTimeout(debounceTimerRef.current);
      }
      if (abortControllerRef.current) {
        abortControllerRef.current.abort();
      }
    };
  }, [content, siteId, siteUrl, serpSnapshotId, debounceMs]);

  // Use server terms when available, fall back to local matching
  const terms = score?.terms ?? localTerms;

  return { score, isLoading, error, terms };
}
