// AniLiberty module for Sora (AsyncJS)
// Author: emp0ry
// Version: 1.0.1

const IMAGE_HOST = "https://anilibria.top";

function fullImg(path) {
  if (!path) return;
  return path.startsWith("http") ? path : `${IMAGE_HOST}${path}`;
}

function pickBestHls(ep) {
  return ep?.hls_1080 || ep?.hls_720 || ep?.hls_480 || null;
}

// ------------------------------------------------------------
// Detect working API domain
// ------------------------------------------------------------
async function checkApiStatus() {
  const domains = [
    "https://anilibria.top/api/v1/",
    "https://aniliberty.top/api/v1/",
    "https://anilibria.wtf/api/v1/"
  ];
  for (const base of domains) {
    try {
      const res = await fetchv2(base + "app/status");
      const data = await res.json();
      if (data?.is_alive || data?.result === "ok") return base;
    } catch (_) {}
  }
  return "https://anilibria.top/api/v1/";
}

// ------------------------------------------------------------
// Search -> JSON string
// ------------------------------------------------------------
async function searchResults(keyword) {
  try {
    const base = await checkApiStatus();
    const url = `${base}app/search/releases?query=${encodeURIComponent(keyword)}&include=id,name.main,poster.src`;

    const res = await fetchv2(url);
    const data = await res.json();

    const out = (Array.isArray(data) ? data : []).map(it => ({
      title: it?.name?.main || "Unknown title",
      image: fullImg(it?.poster?.src),
      href:
        `${base}anime/releases/${it.id}?` +
        [
          "include=name.main,poster.src,description,average_duration_of_episode",
          "episodes.ordinal,episodes.name,episodes.duration",
          "episodes.preview.src",
          "episodes.opening.start,episodes.opening.stop",
          "episodes.ending.start,episodes.ending.stop",
          "episodes.hls_1080,episodes.hls_720,episodes.hls_480"
        ].join(",")
    }));

    if (!out.length) {
      return JSON.stringify([]);;
    }
    return JSON.stringify(out);
  } catch (e) {
    return JSON.stringify([]);;
  }
}

// ------------------------------------------------------------
// Details -> JSON string (Duration: Xm in aliases)
// ------------------------------------------------------------
async function extractDetails(url) {
  try {
    const res = await fetchv2(url);
    const data = await res.json();

    const description = data?.description || "No description available.";
    const mins = Number.isFinite(data?.average_duration_of_episode)
      ? `${data.average_duration_of_episode}m`
      : "Unknown";

    const out = [{
      description,
      aliases: `Duration: ${mins}`,
      airdate: "Unknown"
    }];
    return JSON.stringify(out);
  } catch (e) {
    return JSON.stringify([]);;
  }
}

// ------------------------------------------------------------
// Episodes -> JSON string (with opening/ending skips)
// ------------------------------------------------------------
async function extractEpisodes(url) {
  try {
    const res = await fetchv2(url);
    const data = await res.json();

    const seriesPoster = fullImg(data?.poster?.src);
    const eps = Array.isArray(data?.episodes) ? data.episodes : [];

    const out = eps.map((ep, idx) => {
      const href = pickBestHls(ep);
      if (!href) return null;

      const num = Number.isFinite(ep?.ordinal)
        ? ep.ordinal
        : (Number.isFinite(ep?.sort_order) ? ep.sort_order : (idx + 1));

      const title = ep?.name ? String(ep.name) : `Episode ${num}`;
      const image = fullImg(ep?.preview?.src) || seriesPoster;

      // Build skip blocks only if numbers present
      const opening = (ep?.opening && Number.isFinite(ep.opening.start) && Number.isFinite(ep.opening.stop))
        ? { start: ep.opening.start, stop: ep.opening.stop }
        : undefined;

      const ending = (ep?.ending && Number.isFinite(ep.ending.start) && Number.isFinite(ep.ending.stop))
        ? { start: ep.ending.start, stop: ep.ending.stop }
        : undefined;

      const entry = {
        href,
        number: num,
        title,
        image
      };

      // Attach only when available
      if (opening) entry.opening = opening;
      if (ending) entry.ending = ending;
      if (Number.isFinite(ep?.duration)) entry.duration = ep.duration; // seconds (optional)

      return entry;
    }).filter(Boolean);

    return JSON.stringify(out);
  } catch (e) {
    return JSON.stringify([]);
  }
}

// ------------------------------------------------------------
// Stream -> RAW URL string
// ------------------------------------------------------------
async function extractStreamUrl(url) {
  try {
    return url; // direct HLS
  } catch (e) {
    return null;
  }
}