'use client';

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

export interface ResolutionInfo {
  width: number;
  height: number;
  label: string;
  color: string;
}

const CACHE_PREFIX = 'res:';

function getCached(source: string, id: string | number): ResolutionInfo | null {
  try {
    const raw = sessionStorage.getItem(`${CACHE_PREFIX}${source}:${id}`);
    if (!raw) return null;
    return JSON.parse(raw);
  } catch {
    return null;
  }
}

function setCache(source: string, id: string | number, info: ResolutionInfo) {
  try {
    sessionStorage.setItem(`${CACHE_PREFIX}${source}:${id}`, JSON.stringify(info));
  } catch { /* ignore */ }
}

interface VideoToProbe {
  id: string | number;
  source: string;
}

/**
 * Hook that probes actual video resolutions via m3u8 manifests.
 * Returns a map of "source:id" -> ResolutionInfo.
 * Results are cached in sessionStorage.
 */
export function useResolutionProbe(videos: VideoToProbe[]): {
  resolutions: Record<string, ResolutionInfo | null>;
  isProbing: boolean;
} {
  const [resolutions, setResolutions] = useState<Record<string, ResolutionInfo | null>>({});
  const [isProbing, setIsProbing] = useState(false);
  const abortRef = useRef<AbortController | null>(null);
  // Track which videos we've already started probing to avoid duplicates
  const probedKeysRef = useRef<Set<string>>(new Set());

  useEffect(() => {
    if (!videos || videos.length === 0) return;

    // Check cache first, find which ones need probing
    const cached: Record<string, ResolutionInfo | null> = {};
    const needProbe: VideoToProbe[] = [];

    for (const v of videos) {
      const key = `${v.source}:${v.id}`;
      const cachedInfo = getCached(v.source, v.id);
      if (cachedInfo) {
        cached[key] = cachedInfo;
      } else if (!probedKeysRef.current.has(key)) {
        needProbe.push(v);
        probedKeysRef.current.add(key);
      }
    }

    // Set cached results immediately
    if (Object.keys(cached).length > 0) {
      setResolutions(prev => ({ ...prev, ...cached }));
    }

    if (needProbe.length === 0) return;

    // Abort previous request
    abortRef.current?.abort();
    const controller = new AbortController();
    abortRef.current = controller;

    setIsProbing(true);

    (async () => {
      try {
        const response = await fetch('/api/probe-resolution', {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({ videos: needProbe }),
          signal: controller.signal,
        });

        if (!response.ok || !response.body) {
          setIsProbing(false);
          return;
        }

        const reader = response.body.getReader();
        const decoder = new TextDecoder();
        let buffer = '';

        while (true) {
          const { done, value } = await reader.read();
          if (done) break;
          buffer += decoder.decode(value, { stream: true });
          const lines = buffer.split('\n');
          buffer = lines.pop() || '';

          for (const line of lines) {
            if (!line.startsWith('data: ')) continue;
            try {
              const data = JSON.parse(line.slice(6));
              if (data.done) continue;
              const key = `${data.source}:${data.id}`;
              if (data.resolution) {
                setCache(data.source, data.id, data.resolution);
                setResolutions(prev => ({ ...prev, [key]: data.resolution }));
              } else {
                setResolutions(prev => ({ ...prev, [key]: null }));
              }
            } catch { /* ignore */ }
          }
        }
      } catch (e: any) {
        if (e?.name !== 'AbortError') {
          console.warn('[ResolutionProbe] Failed:', e);
        }
      } finally {
        setIsProbing(false);
      }
    })();

    return () => {
      controller.abort();
    };
  }, [videos]);

  return { resolutions, isProbing };
}
