import { useQuery, useQueryClient } from "@tanstack/react-query";
import { xtreamApi } from "@/lib/xtream";
import { m3uApi } from "@/lib/m3u";
import { stalkerApi } from "@/lib/stalker";
import type { XtreamProfile, Channel, Movie, Series } from "@/types/xtream";

/**
 * v1.4.2 — Anti-ANR Data Hooks
 *
 * KEY CHANGES:
 *   1. Each section (live/movies/series) loads INDEPENDENTLY — no more
 *      Promise.all() that blocks the JS thread with 7000+ items at once.
 *   2. staleTime = 10min so data is cached after first load.
 *   3. usePrefetchProfile loads SEQUENTIALLY (live → movies → series)
 *      with a yield between each to keep the UI responsive.
 *   4. Error boundaries per section — one failing doesn't break the others.
 */

const STALE = 1000 * 60 * 10; // 10 minutes

const isM3U = (p: XtreamProfile) => p.kind === "m3u";
const isStalker = (p: XtreamProfile) => p.kind === "stalker";

const fetchM3UAll = async (p: XtreamProfile) => {
  const entries =
    p.m3uContent && p.m3uContent.trim().length
      ? m3uApi.parsePlaylistText(p.m3uContent)
      : await m3uApi.fetchPlaylist(p.m3uUrl!);
  return m3uApi.classify(entries);
};

const fetchStalkerAll = async (p: XtreamProfile) =>
  stalkerApi.fetchAll(p.portalUrl!, p.macAddress!);

// ── Cached M3U/Stalker result to avoid re-parsing the same playlist ──
let _cachedBulkProfileId: string | null = null;
let _cachedBulk: { channels: Channel[]; movies: Movie[]; series: Series[] } | null = null;

const getBulkCached = async (p: XtreamProfile) => {
  if (_cachedBulkProfileId === p.id && _cachedBulk) return _cachedBulk;
  const result = isStalker(p) ? await fetchStalkerAll(p) : await fetchM3UAll(p);
  _cachedBulkProfileId = p.id ?? null;
  _cachedBulk = result;
  return result;
};

/**
 * Live channels — loaded first (priority).
 * Returns Channel[] from Xtream API, M3U, or Stalker.
 */
export const useLiveChannels = (profile: XtreamProfile | null) =>
  useQuery<Channel[]>({
    queryKey: ["xtream", profile?.id, "live"],
    queryFn: async () => {
      if (!profile) return [];
      try {
        if (isStalker(profile) || isM3U(profile)) {
          return (await getBulkCached(profile)).channels;
        }
        return await xtreamApi.getLiveStreams(profile);
      } catch (e) {
        console.error("[useLiveChannels] Error:", e);
        return [];
      }
    },
    enabled: !!profile,
    staleTime: STALE,
    retry: 2,
    retryDelay: 1000,
  });

/**
 * Movies — loaded AFTER live channels (lower priority).
 * Wrapped in try-catch so a movie API failure doesn't crash the app.
 */
export const useMovies = (profile: XtreamProfile | null) =>
  useQuery<Movie[]>({
    queryKey: ["xtream", profile?.id, "movies"],
    queryFn: async () => {
      if (!profile) return [];
      try {
        if (isStalker(profile) || isM3U(profile)) {
          return (await getBulkCached(profile)).movies;
        }
        return await xtreamApi.getMovies(profile);
      } catch (e) {
        console.error("[useMovies] Error:", e);
        return [];
      }
    },
    enabled: !!profile,
    staleTime: STALE,
    retry: 2,
    retryDelay: 2000,
  });

/**
 * Series — loaded last (lowest priority).
 */
export const useSeries = (profile: XtreamProfile | null) =>
  useQuery<Series[]>({
    queryKey: ["xtream", profile?.id, "series"],
    queryFn: async () => {
      if (!profile) return [];
      try {
        if (isStalker(profile) || isM3U(profile)) {
          return (await getBulkCached(profile)).series;
        }
        return await xtreamApi.getSeries(profile);
      } catch (e) {
        console.error("[useSeries] Error:", e);
        return [];
      }
    },
    enabled: !!profile,
    staleTime: STALE,
    retry: 2,
    retryDelay: 3000,
  });

export const useReloadPlaylist = () => {
  const qc = useQueryClient();
  return (profileId: string) => {
    _cachedBulkProfileId = null;
    _cachedBulk = null;
    qc.invalidateQueries({ queryKey: ["xtream", profileId] });
  };
};

export interface EpgEntry {
  id: string;
  title: string;
  description: string;
  start: string;
  end: string;
  startTimestamp: number;
  stopTimestamp: number;
  nowPlaying: boolean;
}

export const useShortEpg = (
  profile: XtreamProfile | null,
  streamId: string | null | undefined,
) =>
  useQuery<EpgEntry[]>({
    queryKey: ["xtream", profile?.id, "epg", streamId],
    queryFn: async () => {
      if (!profile || !streamId || isM3U(profile) || isStalker(profile))
        return [];
      try {
        return await xtreamApi.getShortEpg(profile, streamId, 6);
      } catch {
        return [];
      }
    },
    enabled:
      !!profile &&
      !!streamId &&
      !isM3U(profile as XtreamProfile) &&
      !isStalker(profile as XtreamProfile),
    staleTime: 1000 * 60 * 5,
  });

/**
 * SEQUENTIAL prefetch — loads live → (yield) → movies → (yield) → series.
 * Each step yields to the event loop so the UI stays responsive.
 * This replaces the old Promise.all() that caused ANR.
 */
export const usePrefetchProfile = () => {
  const qc = useQueryClient();
  return async (profile: XtreamProfile) => {
    // Helper: yield to the event loop for 1 tick so the UI can paint
    const breathe = () => new Promise((r) => setTimeout(r, 0));

    if (isStalker(profile) || isM3U(profile)) {
      const all = await getBulkCached(profile);
      qc.setQueryData(["xtream", profile.id, "live"], all.channels);
      await breathe();
      qc.setQueryData(["xtream", profile.id, "movies"], all.movies);
      await breathe();
      qc.setQueryData(["xtream", profile.id, "series"], all.series);
      return all;
    }

    // SEQUENTIAL — not Promise.all()!
    // Live channels first (highest priority)
    const live = await xtreamApi.getLiveStreams(profile);
    qc.setQueryData(["xtream", profile.id, "live"], live);
    await breathe();

    // Movies second
    let movies: Movie[] = [];
    try {
      movies = await xtreamApi.getMovies(profile);
      qc.setQueryData(["xtream", profile.id, "movies"], movies);
    } catch (e) {
      console.error("[prefetch] Movies failed:", e);
    }
    await breathe();

    // Series last
    let series: Series[] = [];
    try {
      series = await xtreamApi.getSeries(profile);
      qc.setQueryData(["xtream", profile.id, "series"], series);
    } catch (e) {
      console.error("[prefetch] Series failed:", e);
    }

    return { channels: live, movies, series };
  };
};
