/* ═══════════════════════════════════════════════════════
   Kling Motion 2.6 — Frontend (Weavy + KIE.AI)
   ═══════════════════════════════════════════════════════ */

const $ = (id) => document.getElementById(id);

const els = {
  poolBanner: $("pool-banner"),
  poolInfo: $("pool-info"),
  poolInfoFooter: $("pool-info-footer"),

  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"),
  kieMode: $("kie-mode"),

  generateBtn: $("generate-btn"),
  progressContainer: $("progress-container"),
  status: $("status"),
  result: $("result"),
  resultVideo: $("result-video"),
  downloadLink: $("download-link"),

  kieKeyInput: $("kie-api-key-input"),
  kieKeyStatus: $("kie-key-status"),

  // Voucher elements
  loginModal: $("login-modal"),
  voucherInput: $("voucher-input"),
  submitVoucherBtn: $("submit-voucher-btn"),
  modalStatus: $("modal-status"),
  interactiveContainer: $("interactive-container"),
};

const VOUCHER_KEY = "vip_voucher_code";
const TIER_KEY = "vip_voucher_tier";

const state = {
  backend: "weavy",           // "weavy" | "kie"
  image: { url: "", meta: {}, uploading: false },
  video: { url: "", meta: {}, uploading: false },
  recipeId: "",
  voucher: localStorage.getItem(VOUCHER_KEY) || "",
  tier: localStorage.getItem(TIER_KEY) || "",
};

// ═══════════════════════════════════════════════════════
// BACKEND TOGGLE
// ═══════════════════════════════════════════════════════

function switchBackend(mode) {
  state.backend = mode;
  $("btn-weavy").classList.toggle("active", mode === "weavy");
  $("btn-kie").classList.toggle("active", mode === "kie");
  $("weavy-section").style.display = mode === "weavy" ? "block" : "none";
  $("kie-section").style.display = mode === "kie" ? "block" : "none";
  $("weavy-settings").style.display = mode === "weavy" ? "block" : "none";
  $("kie-settings").style.display = mode === "kie" ? "block" : "none";
  // Reset uploads when switching (URLs from different upload endpoints)
  clearPreview("image");
  clearPreview("video");
}

// ═══════════════════════════════════════════════════════
// KIE.AI KEY MANAGEMENT
// ═══════════════════════════════════════════════════════

async function checkKieKey() {
  try {
    const r = await fetch("/api/kie/config");
    const cfg = await r.json();
    if (cfg.configured) {
      els.kieKeyStatus.className = "kie-status ok";
      els.kieKeyStatus.textContent = `✅ KIE.AI key: ${cfg.masked}`;
    } else {
      els.kieKeyStatus.className = "kie-status warn";
      els.kieKeyStatus.textContent = "⚠️ KIE.AI API key belum dikonfigurasi";
    }
  } catch (e) {
    els.kieKeyStatus.className = "kie-status warn";
    els.kieKeyStatus.textContent = "⚠️ Gagal cek KIE status";
  }
}

async function saveKieKey() {
  const key = els.kieKeyInput.value.trim();
  if (!key) { alert("Masukkan API key dulu!"); return; }
  try {
    const r = await fetch("/api/kie/key", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ apiKey: key }),
    });
    const data = await r.json();
    if (data.ok) {
      els.kieKeyInput.value = "";
      els.kieKeyStatus.className = "kie-status ok";
      els.kieKeyStatus.textContent = `✅ KIE.AI key tersimpan: ${data.masked}`;
    } else {
      alert("Gagal simpan key: " + (data.error || "unknown"));
    }
  } catch (e) {
    alert("Error: " + e.message);
  }
}

// ═══════════════════════════════════════════════════════
// STATUS
// ═══════════════════════════════════════════════════════

function setStatus(text, type) {
  type = 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;
}

// ═══════════════════════════════════════════════════════
// FILE UPLOAD
// ═══════════════════════════════════════════════════════

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

  const endpoint = state.backend === "kie" ? "/api/kie/upload" : "/api/upload";
  const fd = new FormData();
  fd.append("file", file);

  try {
    const r = await fetch(endpoint, {
      method: "POST",
      headers: { "x-voucher-code": state.voucher },
      body: fd
    });
    const data = await r.json();
    if (!r.ok) throw new Error(data.error || "Upload failed");

    let url;
    if (state.backend === "kie") {
      // KIE response: { ok: true, url: "...", fileName: "..." }
      url = data.url;
      if (!url) throw new Error("KIE upload sukses tapi URL tidak ditemukan");
    } else {
      // Weavy response: { asset: { url: ... } }
      const asset = data.asset || data.file || data;
      url = asset.url || asset.secureUrl || asset.secure_url;
      if (!url) throw new Error("Upload sukses tapi URL tidak ditemukan");

      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,
      };
    }

    state[kind].url = url;
    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.imagePreviewBox.hidden = false;
    els.imageDz.classList.add("compact");
  } else {
    els.videoPreview.src = url;
    els.videoPreviewBox.hidden = false;
    els.videoDz.classList.add("compact");
  }
}

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

// ═══════════════════════════════════════════════════════
// PREMIUM PROGRESS ANIMATOR (REAL-TIME & SMOOTH)
// ═══════════════════════════════════════════════════════

let progressInterval = null;
let progressTarget = 0;
let progressCurrent = 0;

function startProgressSimulation() {
  stopProgressSimulation();
  progressCurrent = 0;
  progressTarget = 5; // Start at 5%
  updateProgressUI(progressCurrent, "Menghubungkan ke API server...");
  
  if (els.progressContainer) els.progressContainer.hidden = false;

  // Reset progress bar styling (e.g. from any previous errors)
  const progressBarFill = document.getElementById("progress-bar-fill");
  if (progressBarFill) {
    progressBarFill.style.background = "";
    progressBarFill.style.boxShadow = "";
  }

  // Smoothly interpolate current toward target
  progressInterval = setInterval(() => {
    if (progressCurrent < progressTarget) {
      const diff = progressTarget - progressCurrent;
      const step = Math.max(0.1, diff * 0.12); // Smooth logarithmic easing
      progressCurrent = parseFloat((progressCurrent + step).toFixed(1));
      if (progressCurrent > progressTarget) progressCurrent = progressTarget;
      updateProgressUI(progressCurrent);
    }
  }, 100);
}

function setProgressTarget(target, statusText) {
  progressTarget = Math.min(99, Math.max(progressTarget, target));
  if (statusText) {
    updateProgressUI(progressCurrent, statusText);
  }
}

function updateProgressUI(pct, statusText) {
  const percentText = Math.floor(pct) + "%";
  const progressBarFill = document.getElementById("progress-bar-fill");
  const progressPercent = document.getElementById("progress-percent");
  const progressStatusText = document.getElementById("progress-status-text");

  if (progressBarFill) progressBarFill.style.width = percentText;
  if (progressPercent) progressPercent.textContent = percentText;
  if (progressStatusText && statusText) {
    progressStatusText.textContent = statusText;
  }
}

function stopProgressSimulation() {
  if (progressInterval) {
    clearInterval(progressInterval);
    progressInterval = null;
  }
}

function completeProgress(statusText) {
  stopProgressSimulation();
  progressCurrent = 100;
  progressTarget = 100;
  updateProgressUI(100, statusText || "Selesai ✓");
  setTimeout(() => {
    if (els.progressContainer) els.progressContainer.hidden = true;
  }, 1500);
}

function failProgress(statusText) {
  stopProgressSimulation();
  updateProgressUI(progressCurrent, statusText || "Gagal!");
  const progressBarFill = document.getElementById("progress-bar-fill");
  if (progressBarFill) {
    progressBarFill.style.background = "var(--accent)";
    progressBarFill.style.boxShadow = "0 0 10px var(--accent)";
  }
  setTimeout(() => {
    if (els.progressContainer) els.progressContainer.hidden = true;
  }, 3000);
}

// ═══════════════════════════════════════════════════════
// GENERATE — KIE.AI Direct
// ═══════════════════════════════════════════════════════

async function pollKieTask(taskId) {
  const maxAttempts = 120; // 6 minutes max
  let attempt = 0;
  while (attempt < maxAttempts) {
    await new Promise((r) => setTimeout(r, 3000));
    attempt++;

    const r = await fetch(`/api/kie/task/${encodeURIComponent(taskId)}`);
    const data = await r.json();

    if (!r.ok) {
      if (attempt > 5) throw new Error(data.error || "Polling failed");
      continue;
    }

    const st = data.state;
    const elapsedSec = attempt * 3;
    
    // Calculate percentage based on progress returned or fallback
    let pct = 15;
    if (data.progress) {
      pct = 15 + Math.floor(data.progress * 0.85);
    } else {
      pct = Math.min(98, 15 + Math.floor((elapsedSec / 90) * 80));
    }
    
    let statusMsg = "Sedang merender gerakan video...";
    if (st === "queuing") {
      statusMsg = "Mengantre di server...";
    } else if (st === "generating") {
      statusMsg = `GPU sedang memproses frame video... (${data.progress || Math.floor((elapsedSec/90)*100)}%)`;
    }
    
    setProgressTarget(pct, statusMsg);

    if (st === "success" && data.resultUrl) {
      return data.resultUrl;
    }
    if (st === "fail") {
      throw new Error(`Task gagal: ${data.failMsg || "unknown"}`);
    }
  }
  throw new Error("Polling timeout (6 menit).");
}

async function generateViaKie() {
  const body = {
    imageUrl: state.image.url,
    videoUrl: state.video.url,
    prompt: els.prompt.value.trim(),
    characterOrientation: els.orientation.value,
    mode: els.kieMode.value,
  };

  startProgressSimulation();
  setProgressTarget(8, "Menyiapkan material dan menghubungi server...");
  const r = await fetch("/api/kie/generate", {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      "x-voucher-code": state.voucher
    },
    body: JSON.stringify(body),
  });
  const data = await r.json();
  if (!r.ok) throw new Error(data.error || "Generate failed");

  const taskId = data.taskId;
  setProgressTarget(15, "Menunggu antrian server...");

  const videoUrl = await pollKieTask(taskId);
  return videoUrl;
}

// ═══════════════════════════════════════════════════════
// GENERATE — Weavy
// ═══════════════════════════════════════════════════════

async function pollWeavyBatch(accountId, batchId, runId, recipeId) {
  const maxAttempts = 120;
  const estimatedMaxTimeSec = 85; // Typical Kling generation time via Weavy is ~85 seconds

  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;
    }
    
    // Calculate realistic and smooth real-time percentage
    const elapsedSec = (i + 1) * 3;
    const percent = Math.min(98, 15 + Math.floor((elapsedSec / estimatedMaxTimeSec) * 80));
    
    let statusMsg = "Menunggu antrian server...";
    if (data.status) {
      const st = String(data.status).toUpperCase();
      if (st === "FAILED" || st === "CANCELLED") {
        throw new Error(data.error || `Task ${st.toLowerCase()} di Weavy.`);
      }
      if (st === "PENDING" || st === "QUEUED") {
        statusMsg = "Mengantre di server...";
      } else if (st === "RUNNING") {
        if (percent > 85) statusMsg = "Hampir selesai, memproses audio video...";
        else if (percent > 55) statusMsg = "Menyinkronkan gerakan karakter...";
        else statusMsg = "GPU sedang merender frame video...";
      } else {
        statusMsg = `Status: ${data.status}...`;
      }
    } else {
      if (percent > 85) statusMsg = "Hampir selesai, memproses audio video...";
      else if (percent > 55) statusMsg = "Menyinkronkan gerakan karakter...";
      else statusMsg = "GPU sedang merender frame video...";
    }

    setProgressTarget(percent, statusMsg);

    if (data.found && data.url) return data.url;
  }
  throw new Error("Polling timeout (6 menit).");
}

async function generateViaWeavy() {
  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,
  };

  startProgressSimulation();
  setProgressTarget(8, "Menyiapkan material dan menghubungi server...");
  const res = await fetch("/api/generate", {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      "x-voucher-code": state.voucher
    },
    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 { _accountId: accountId, _recipeId: recipeId, batchId } = data;
  const runId = data.recipeRuns?.[0]?.id;

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

  setProgressTarget(15, "Mengantre untuk render video...");
  const videoUrl = await pollWeavyBatch(accountId, batchId, runId, recipeId);
  return videoUrl;
}

// ═══════════════════════════════════════════════════════
// GENERATE BUTTON
// ═══════════════════════════════════════════════════════

$("generate-btn").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(""); // Clear text status

  try {
    let videoUrl;
    if (state.backend === "kie") {
      videoUrl = await generateViaKie();
    } else {
      videoUrl = await generateViaWeavy();
    }

    completeProgress("Video berhasil dibuat!");
    els.resultVideo.src = videoUrl;
    els.downloadLink.href = videoUrl;
    els.result.hidden = false;
    refreshPool();
  } catch (err) {
    failProgress("Gagal: " + err.message);
    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;
    const txt = `${cfg.availableAccounts}/${cfg.totalAccounts} aktif`;
    if (els.poolInfo) els.poolInfo.textContent = txt;
    if (els.poolInfoFooter) els.poolInfoFooter.textContent = txt;
    if (cfg.availableAccounts === 0 && state.backend === "weavy") {
      if (els.poolBanner) {
        els.poolBanner.textContent = "⚠️ Belum ada akun aktif di pool. Hubungi admin atau pakai KIE.AI Direct.";
        els.poolBanner.hidden = false;
      }
    } else {
      if (els.poolBanner) els.poolBanner.hidden = true;
    }
  } catch {}
}

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

// ─── Member Voucher Portal (Overlay) & Tier Restrictions ─────────────────────

function showLoginModal() {
  if (els.loginModal) {
    els.loginModal.style.display = "flex";
    els.voucherInput.focus();
  }
}

function hideLoginModal() {
  if (els.loginModal) els.loginModal.style.display = "none";
}

function showModalStatus(text, type = "error") {
  if (!els.modalStatus) return;
  if (!text) { els.modalStatus.hidden = true; return; }
  els.modalStatus.hidden = false;
  els.modalStatus.textContent = text;
  els.modalStatus.className = "status " + type;
}

async function submitVoucher() {
  const code = els.voucherInput.value.trim().toUpperCase();
  if (!code) {
    showModalStatus("Masukkan kode voucher VIP Anda.");
    return;
  }
  
  showModalStatus("Memverifikasi...", "warn");
  try {
    const r = await fetch("/api/auth/login", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ voucherCode: code })
    });
    const data = await r.json();
    if (!r.ok) throw new Error(data.error || "Aktivasi gagal");
    
    // Save state
    state.voucher = code;
    state.tier = data.tier;
    localStorage.setItem(VOUCHER_KEY, code);
    localStorage.setItem(TIER_KEY, data.tier);
    
    hideLoginModal();
    applyTierLock();
    showModalStatus("");
  } catch (err) {
    showModalStatus("Gagal: " + err.message, "error");
  }
}

function applyTierLock() {
  if (!state.voucher) return; // Not logged in yet
  
  if (state.tier === "standard") {
    // Lock Model & Version to standard settings
    els.modelType.value = "Standard";
    els.modelVersion.value = "V2.6";
    els.modelType.disabled = true;
    els.modelVersion.disabled = true;
    
    // Render lock notification banner
    let hintEl = $("tier-lock-hint");
    if (!hintEl) {
      hintEl = document.createElement("div");
      hintEl.id = "tier-lock-hint";
      hintEl.style.fontSize = "0.8rem";
      hintEl.style.color = "var(--warn)";
      hintEl.style.marginTop = "0.5rem";
      hintEl.style.display = "flex";
      hintEl.style.alignItems = "center";
      hintEl.style.gap = "6px";
      hintEl.textContent = "🔒 Pilihan Model & Versi dikunci di plan Standard. Upgrade ke Pro untuk membuka 3.0 & Pro.";
      els.modelType.closest(".grid-2").after(hintEl);
    }
  } else {
    // Pro plan: unlock both Model and Version
    els.modelType.disabled = false;
    els.modelVersion.disabled = false;
    const hintEl = $("tier-lock-hint");
    if (hintEl) hintEl.remove();
  }
}

// Bind Submit Button
if (els.submitVoucherBtn) {
  els.submitVoucherBtn.addEventListener("click", submitVoucher);
}
if (els.voucherInput) {
  els.voucherInput.addEventListener("keydown", (e) => {
    if (e.key === "Enter") submitVoucher();
  });
}

// Intercept Click Events to block unauthorized usage
if (els.interactiveContainer) {
  els.interactiveContainer.addEventListener("click", (e) => {
    if (!state.voucher) {
      e.preventDefault();
      e.stopPropagation();
      showLoginModal();
    }
  }, true); // useCapture is true
}

// Initialize Tier Lock check on page load
applyTierLock();
