const $ = (id) => document.getElementById(id);
const els = {
  poolBanner: $("pool-banner"),
  poolInfo: $("pool-info"),

  imageDz: $("image-dropzone"),
  imageFile: $("image-file"),
  imagePreview: $("image-preview"),
  imagePreviewBox: $("image-preview-box"),

  videoDz: $("video-dropzone"),
  videoFile: $("video-file"),
  videoPreview: $("video-preview"),
  videoPreviewBox: $("video-preview-box"),

  prompt: $("prompt"),
  modelType: $("model_type"),
  modelVersion: $("model_version"),
  orientation: $("character_orientation"),
  keepSound: $("keep_original_sound"),

  generateBtn: $("generate-btn"),
  status: $("status"),
  result: $("result"),
  resultVideo: $("result-video"),
  downloadLink: $("download-link"),
};

const state = {
  image: { url: "", meta: {}, uploading: false },
  video: { url: "", meta: {}, uploading: false },
  recipeId: "",
};

function setStatus(text, type = "") {
  if (!text) { els.status.hidden = true; return; }
  els.status.hidden = false;
  els.status.textContent = text;
  els.status.className = `status ${type}`;
}

function updateGenerateBtn() {
  const ready = state.image.url && state.video.url && !state.image.uploading && !state.video.uploading;
  els.generateBtn.disabled = !ready;
}

// ─── Upload ─────────────────────────────────────────────────────────────────

async function uploadFile(kind, file) {
  state[kind].uploading = true;
  updateGenerateBtn();
  setStatus(`Uploading ${kind}: ${file.name}...`);

  const fd = new FormData();
  fd.append("file", file);

  try {
    const r = await fetch("/api/upload", { method: "POST", body: fd });
    const data = await r.json();
    if (!r.ok) throw new Error(data.error || "Upload failed");

    const asset = data.asset || data.file || data;
    const url = asset.url || asset.secureUrl || asset.secure_url;
    if (!url) throw new Error("Upload sukses tapi URL tidak ditemukan");

    state[kind].url = url;
    state[kind].meta = {
      width: asset.width, height: asset.height,
      duration: asset.duration, fps: asset.fps, hasAudio: asset.hasAudio,
      thumbnailUrl: asset.thumbnailUrl,
      publicId: asset.publicId || asset.public_id,
      id: asset.id, name: asset.name || file.name,
    };

    showPreview(kind, url);
    setStatus(`${kind} uploaded ✓`, "done");
    setTimeout(() => setStatus(""), 1500);
  } catch (err) {
    state[kind].url = ""; state[kind].meta = {};
    setStatus(`Upload error (${kind}): ${err.message}`, "error");
  } finally {
    state[kind].uploading = false;
    updateGenerateBtn();
  }
}

function showPreview(kind, url) {
  if (kind === "image") {
    els.imagePreview.src = url;
    els.imagePreview.onload = () => {
      if (!state.image.meta.width) state.image.meta.width = els.imagePreview.naturalWidth;
      if (!state.image.meta.height) state.image.meta.height = els.imagePreview.naturalHeight;
    };
    els.imagePreviewBox.hidden = false;
    els.imageDz.classList.add("compact");
  } else {
    els.videoPreview.src = url;
    els.videoPreview.onloadedmetadata = () => {
      if (!state.video.meta.width) state.video.meta.width = els.videoPreview.videoWidth;
      if (!state.video.meta.height) state.video.meta.height = els.videoPreview.videoHeight;
      if (!state.video.meta.duration) state.video.meta.duration = +els.videoPreview.duration?.toFixed(1) || 0;
    };
    els.videoPreviewBox.hidden = false;
    els.videoDz.classList.add("compact");
  }
}

function clearPreview(kind) {
  state[kind] = { url: "", meta: {}, uploading: false };
  if (kind === "image") {
    els.imagePreview.removeAttribute("src");
    els.imagePreviewBox.hidden = true;
    els.imageDz.classList.remove("compact");
    els.imageFile.value = "";
  } else {
    els.videoPreview.removeAttribute("src");
    els.videoPreviewBox.hidden = true;
    els.videoDz.classList.remove("compact");
    els.videoFile.value = "";
  }
  updateGenerateBtn();
}

function bindDropzone(kind) {
  const dz = kind === "image" ? els.imageDz : els.videoDz;
  const input = kind === "image" ? els.imageFile : els.videoFile;
  const acceptPrefix = kind === "image" ? "image/" : "video/";
  dz.addEventListener("click", (e) => {
    if (e.target.classList.contains("remove-btn")) return;
    if (e.target.tagName === "VIDEO" || e.target.tagName === "IMG") return;
    input.click();
  });
  input.addEventListener("change", (e) => {
    const file = e.target.files[0];
    if (file && file.type.startsWith(acceptPrefix)) uploadFile(kind, file);
  });
  dz.addEventListener("dragover", (e) => { e.preventDefault(); dz.classList.add("dragging"); });
  dz.addEventListener("dragleave", () => dz.classList.remove("dragging"));
  dz.addEventListener("drop", (e) => {
    e.preventDefault();
    dz.classList.remove("dragging");
    const file = e.dataTransfer.files[0];
    if (file && file.type.startsWith(acceptPrefix)) uploadFile(kind, file);
  });
}

document.querySelectorAll(".remove-btn").forEach((btn) => {
  btn.addEventListener("click", (e) => {
    e.stopPropagation();
    clearPreview(btn.dataset.target);
  });
});

bindDropzone("image");
bindDropzone("video");

// ─── Generate + poll ────────────────────────────────────────────────────────

async function pollUntilDone(accountId, batchId, runId, recipeId, onTick) {
  const maxAttempts = 120;
  for (let i = 0; i < maxAttempts; i++) {
    await new Promise((r) => setTimeout(r, 3000));
    const url = `/api/poll/${accountId}/${batchId}?recipeId=${encodeURIComponent(recipeId)}&runId=${encodeURIComponent(runId)}`;
    const res = await fetch(url);
    const data = await res.json();
    if (!res.ok) {
      if (i > 5) throw new Error(data.error || "Polling failed");
      continue;
    }
    onTick?.(data, i);
    if (data.found && data.url) return { url: data.url, source: data.source };
  }
  throw new Error("Polling timeout (6 menit). Tab Weavy harus terbuka agar hasil bisa terbaca.");
}

els.generateBtn.addEventListener("click", async () => {
  if (!state.image.url || !state.video.url) {
    return setStatus("Image dan Video wajib di-upload.", "error");
  }

  els.generateBtn.disabled = true;
  els.result.hidden = true;
  setStatus("Mengirim ke Weavy...");

  try {
    const body = {
      imageUrl: state.image.url,
      imageMeta: state.image.meta,
      videoUrl: state.video.url,
      videoMeta: state.video.meta,
      prompt: els.prompt.value,
      modelType: els.modelType.value,
      version: els.modelVersion.value,
      characterOrientation: els.orientation.value,
      keepOriginalSound: els.keepSound.checked,
      numberOfRuns: 1,
    };

    const res = await fetch("/api/generate", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify(body),
    });
    const data = await res.json();
    if (!res.ok) throw new Error(typeof data.error === "string" ? data.error : JSON.stringify(data.error || data));

    const accountLabel = data._accountLabel || "?";
    const accountId = data._accountId;
    const recipeId = data._recipeId;
    const batchId = data.batchId;
    const runId = data.recipeRuns?.[0]?.id;

    if (!batchId || !accountId) {
      throw new Error("Response tidak lengkap (batchId/accountId)");
    }

    setStatus(`[${accountLabel}] Job submitted (${batchId}). Polling status... (1-3 menit)`);

    const polled = await pollUntilDone(accountId, batchId, runId, recipeId, (info, i) => {
      const st = info.status ? ` · status: ${info.status}` : "";
      setStatus(`[${accountLabel}] [${i + 1}] menunggu hasil${st}...`);
    });

    els.resultVideo.src = polled.url;
    els.downloadLink.href = polled.url;
    els.result.hidden = false;
    setStatus(`[${accountLabel}] Selesai ✓`, "done");
    refreshPool();
  } catch (err) {
    setStatus(`Error: ${err.message}`, "error");
  } finally {
    updateGenerateBtn();
  }
});

// ─── Bootstrap ──────────────────────────────────────────────────────────────

async function refreshPool() {
  try {
    const r = await fetch("/api/config");
    const cfg = await r.json();
    state.recipeId = cfg.defaultRecipeId;
    els.poolInfo.textContent = `${cfg.availableAccounts}/${cfg.totalAccounts} aktif`;
    if (cfg.availableAccounts === 0) {
      els.poolBanner.textContent = "⚠️ Belum ada akun aktif di pool. Hubungi admin.";
      els.poolBanner.hidden = false;
      els.generateBtn.disabled = true;
    } else {
      els.poolBanner.hidden = true;
    }
  } catch {}
}

refreshPool();
setInterval(refreshPool, 30_000);
updateGenerateBtn();
