// AnimeVost for Sora (AsyncJS)
// Author: emp0ry
// Version: 1.0.0

const API_BASE = "https://api.animevost.org/v1/";
const FORM_CT  = "application/x-www-form-urlencoded; charset=UTF-8";

// --- utils ---
function encodeForm(fields) {
  return Object.keys(fields)
    .map(k => `${encodeURIComponent(k)}=${encodeURIComponent(fields[k])}`)
    .join("&");
}

async function postForm(url, fields) {
  const bodyStr = encodeForm(fields);
  try {
    const resA = await fetchv2(url, { "Content-Type": FORM_CT }, "POST", bodyStr);
    if (resA && typeof resA.text === "function") return resA;
  } catch (_) {}
  return await fetchv2(url, { method: "POST", headers: { "Content-Type": FORM_CT }, body: bodyStr });
}

async function parseJsonSafe(res) {
  const txt = await res.text();
  try { return JSON.parse(txt); }
  catch { return JSON.parse(txt.replace(/^\uFEFF/, "").trim()); }
}

function cleanTitle(raw) {
  if (!raw || typeof raw !== "string") return "Unknown title";
  let t = raw.split(" /")[0];
  return t.replace(/\s*\[.*?\]\s*$/g, "").trim() || "Unknown title";
}

function htmlToText(html) {
  if (!html || typeof html !== "string") return "";
  return html
    .replace(/<br\s*\/?>/gi, "\n")
    .replace(/<\/p>/gi, "\n")
    .replace(/<[^>]+>/g, "")
    .replace(/\n{3,}/g, "\n\n")
    .trim();
}

// Pack payload into href to avoid relying on global state.
function makeHrefFromPayload(obj) {
  return `animevost://payload/${encodeURIComponent(JSON.stringify(obj))}`;
}
function readPayloadFromHref(href) {
  const m = String(href).match(/^animevost:\/\/payload\/(.+)$/);
  if (!m) return null;
  try { return JSON.parse(decodeURIComponent(m[1])); } catch { return null; }
}
function parseIdFromAny(hrefOrId) {
  const p = readPayloadFromHref(hrefOrId);
  if (p && p.id) return parseInt(p.id, 10);
  const m1 = String(hrefOrId).match(/^animevost:\/\/release\/(\d+)$/);
  if (m1) return parseInt(m1[1], 10);
  const m2 = String(hrefOrId).match(/[?&]id=(\d+)/);
  if (m2) return parseInt(m2[1], 10);
  if (/^\d+$/.test(String(hrefOrId))) return parseInt(hrefOrId, 10);
  return null;
}

// --- search (POST /search) ---
async function searchResults(keyword) {
  try {
    let res  = await postForm(API_BASE + "search", { name: String(keyword) });
    let json = await parseJsonSafe(res);

    if (json?.error || !Array.isArray(json?.data) || json.data.length === 0) {
      res  = await postForm(API_BASE + "search", { name: `"${String(keyword)}"` });
      json = await parseJsonSafe(res);
    }

    if (json?.error) {
      return JSON.stringify([]);
    }

    const list = Array.isArray(json?.data) ? json.data : [];
    if (!list.length) {
      return JSON.stringify([]);
    }

    const tiles = list.map(item => {
      const payload = {
        id: item.id,
        title: cleanTitle(item.title),
        description: htmlToText(item.description || ""),
        year: item.year || "",
        type: item.type || "",
        image: item.urlImagePreview || ""
      };
      return {
        title: payload.title,
        image: payload.image,
        href:  makeHrefFromPayload(payload)
      };
    });

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

// --- details (from payload) ---
async function extractDetails(href) {
  try {
    const p = readPayloadFromHref(href);
    const out = [{
      description: p?.description || "No description available.",
      aliases:     `Type: ${p?.type || "Unknown"}`,
      airdate:     p?.year ? String(p.year) : "Unknown"
    }];
    return JSON.stringify(out);
  } catch (e) {
    return JSON.stringify([]);
  }
}

// --- episodes (POST /playlist) ---
async function extractEpisodes(href) {
  try {
    const p  = readPayloadFromHref(href);
    const id = p?.id ?? parseIdFromAny(href);
    if (!id) {
      return JSON.stringify([]);
    }

    const res = await postForm(API_BASE + "playlist", { id: String(id) });
    const arr = await parseJsonSafe(res);

    if (!Array.isArray(arr)) return JSON.stringify([]);

    const out = arr.map((ep, idx) => {
      const name = ep?.name || "";
      const m = name.match(/(\d+)/);
      const num = m ? parseInt(m[1], 10) : (idx + 1);
      const link = ep?.hd || ep?.std || null;
      if (!link) return null;

      return {
        number: num,
        title:  name || `Episode ${num}`,
        image:  ep?.preview || "",
        href:   link
      };
    }).filter(Boolean);

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

// --- stream ---
async function extractStreamUrl(url) {
  try { return url; } catch { return null; }
}
