import { browserWeavyFetch } from "./weavy-client-playwright.js";

const WEAVY_API = "https://api.weavy.ai";

async function weavyGet(path, token) {
  const r = await browserWeavyFetch(WEAVY_API + path, {
    headers: {
      accept: "application/json, text/plain, */*",
      "accept-language": "id-ID,id;q=0.9,en-US;q=0.8,en;q=0.7",
      authorization: `Bearer ${token}`,
      "x-weavy-auth-provider": "firebase",
      "x-app-version": "4.1.577",
      "x-app-recipeid": path.split("/recipes/")[1]?.split("/")[0] || "",
    },
  });
  const text = await r.text();
  let json = null;
  try { json = text ? JSON.parse(text) : null; } catch {}
  return { ok: r.ok, status: r.status, json, text };
}

// Recursively walk for a video URL with type:"video"
export function findVideoUrl(payload) {
  const stack = [payload];
  const seen = new Set();
  while (stack.length) {
    const v = stack.pop();
    if (!v || typeof v !== "object" || seen.has(v)) continue;
    seen.add(v);
    if (Array.isArray(v)) { stack.push(...v); continue; }
    if (v.type === "video" && typeof v.url === "string") return v.url;
    for (const k of Object.keys(v)) stack.push(v[k]);
  }
  return null;
}

// Walk for any media URL (video first, fall back to image), useful for non-video recipes
export function findMediaUrl(payload) {
  const v = findVideoUrl(payload);
  if (v) return v;
  // try direct .url string fields that look like media URLs
  const stack = [payload];
  const seen = new Set();
  while (stack.length) {
    const x = stack.pop();
    if (!x || typeof x !== "object" || seen.has(x)) continue;
    seen.add(x);
    if (Array.isArray(x)) { stack.push(...x); continue; }
    if (typeof x.url === "string" && /media\.weavy\.ai\/(video|image)\/upload/.test(x.url)) {
      return x.url;
    }
    for (const k of Object.keys(x)) stack.push(x[k]);
  }
  return null;
}

// Walk for a status string anywhere in payload
export function findStatus(payload) {
  const stack = [payload];
  const seen = new Set();
  let result = null;
  while (stack.length) {
    const v = stack.pop();
    if (!v || typeof v !== "object" || seen.has(v)) continue;
    seen.add(v);
    if (Array.isArray(v)) { stack.push(...v); continue; }
    if (typeof v.status === "string" && /^(COMPLETED|FAILED|CANCELLED|RUNNING|PENDING)$/i.test(v.status)) {
      result = v;
    }
    for (const k of Object.keys(v)) stack.push(v[k]);
  }
  return result;
}

// Walk for a duration number anywhere in payload (seconds or ms)
export function findDuration(payload) {
  const stack = [payload];
  const seen = new Set();
  while (stack.length) {
    const v = stack.pop();
    if (!v || typeof v !== "object" || seen.has(v)) continue;
    seen.add(v);
    if (Array.isArray(v)) { stack.push(...v); continue; }
    // Common duration field names from Weavy API
    if (typeof v.duration === "number" && v.duration > 0) {
      // If value > 1000, likely in milliseconds
      return v.duration > 1000 ? v.duration / 1000 : v.duration;
    }
    if (typeof v.duration_seconds === "number" && v.duration_seconds > 0) return v.duration_seconds;
    if (typeof v.duration_ms === "number" && v.duration_ms > 0) return v.duration_ms / 1000;
    for (const k of Object.keys(v)) stack.push(v[k]);
  }
  return null;
}

// One-shot poll: official Weavy status endpoint
export async function pollBatchStatus({ token, recipeId, batchId }) {
  const path = `/api/v1/batches/recipes/${recipeId}/batches/${batchId}/status`;
  const res = await weavyGet(path, token);
  if (!res.ok) {
    return { ok: false, status: res.status, error: res.json?.message || res.text };
  }
  const payload = res.json;
  const url = findMediaUrl(payload);
  const statusObj = findStatus(payload);
  const duration = findDuration(payload);
  return {
    ok: true,
    raw: payload,
    url,
    duration,
    status: statusObj?.status || null,
    error: statusObj?.error || null,
  };
}
