// Concat view — merge split stream recordings into one file.

import { h, stem, dirname, joinPath } from "../dom";
import { FileList } from "../filelist";
import { makeProgress, toast } from "../ui";
import {
  pickVideos, pickFolder, startConcat, cancel, deleteFiles, bililiveRename,
  onConcatProgress, reveal,
} from "../api";

const EXTS = [".mp4", ".mkv", ".mov", ".avi", ".ts"];

export interface View { el: HTMLElement; onDrop: (paths: string[]) => void; }

export function buildConcat(): View {
  let running = false;
  let lastOutput: string | null = null;

  const nameInput = h("input", { class: "input grow", placeholder: "output_concat" }) as HTMLInputElement;
  const extSelect = h("select", { class: "input", style: "width:96px" },
    ...EXTS.map((e) => h("option", { value: e }, e))) as HTMLSelectElement;
  const dirInput = h("input", { class: "input grow", placeholder: "Choose output folder…" }) as HTMLInputElement;
  const renamePreview = h("div", { class: "rename-preview" });
  const renameBtn = h("button", { class: "btn accent-soft", disabled: true }, "✨ Rename") as HTMLButtonElement;
  const delChk = h("input", { type: "checkbox", class: "checkbox" }) as HTMLInputElement;

  const listEl = h("div", { class: "list" });
  const totalEl = h("div", { class: "faint" }, "No files");
  const files = new FileList(listEl, totalEl, refresh);

  const startBtn = h("button", { class: "btn primary lg", disabled: true }, "▶  Start Concatenation") as HTMLButtonElement;
  const stopBtn = h("button", { class: "btn danger", disabled: true }, "■ Stop") as HTMLButtonElement;
  const progress = makeProgress();

  const dropzone = h("div", { class: "dropzone" },
    h("div", { style: "font-size:24px;margin-bottom:6px" }, "📂"),
    h("div", {}, "Drag & drop videos here, or "),
    h("button", { class: "btn", style: "margin-top:10px", onclick: pick }, "＋ Add Videos"),
  );

  async function pick() {
    const sel = await pickVideos();
    if (sel.length) addFiles(sel);
  }

  async function addFiles(paths: string[]) {
    await files.add(paths);
    if (!dirInput.value.trim() && files.items.length) {
      dirInput.value = dirname(files.items[0].path);
    }
    if ((!nameInput.value.trim() || nameInput.value === "output_concat") && files.items.length) {
      nameInput.value = stem(files.items[0].path);
    }
    refresh();
  }

  function outPath(): string {
    const d = dirInput.value.trim(), n = nameInput.value.trim();
    if (!d || !n) return "";
    return joinPath(d, n + extSelect.value);
  }

  async function refresh() {
    const ok = !running && files.checkedPaths().length > 0 && !!dirInput.value.trim() && !!nameInput.value.trim();
    startBtn.disabled = !ok;
    // BiliBili rename preview
    const renamed = await bililiveRename(nameInput.value.trim());
    if (renamed && renamed !== nameInput.value.trim()) {
      renamePreview.textContent = `→ ${renamed}`;
      renameBtn.disabled = false;
    } else {
      renamePreview.textContent = "";
      renameBtn.disabled = true;
    }
  }

  renameBtn.addEventListener("click", async () => {
    const renamed = await bililiveRename(nameInput.value.trim());
    if (renamed) { nameInput.value = renamed; refresh(); }
  });
  nameInput.addEventListener("input", refresh);
  dirInput.addEventListener("input", refresh);
  extSelect.addEventListener("change", refresh);

  async function start() {
    const checked = files.checkedPaths();
    const out = outPath();
    if (!checked.length || !out) return;
    if (checked.some((f) => stem(f) === stem(out))) {
      toast("Output name matches a source file — choose another.", "err");
      return;
    }

    running = true;
    startBtn.disabled = true;
    stopBtn.disabled = false;
    progress.reset();
    progress.set(0, "Starting…");

    const un = await onConcatProgress((p) => {
      progress.set(p.pct, p.status, { elapsed: p.elapsed, eta: p.eta, speed: p.speed });
    });

    try {
      const res = await startConcat(checked, out);
      lastOutput = res.output;
      progress.set(1, `Done — ${res.size_mb.toFixed(1)} MB`);
      toast("Concatenation complete", "ok");
      revealBtn.style.display = "";

      if (delChk.checked) {
        const n = await deleteFiles(checked);
        if (n) toast(`Deleted ${n} original file(s)`, "ok");
      }
    } catch (e) {
      const msg = String(e);
      if (msg.includes("__cancelled__")) { progress.set(0, "Stopped by user."); }
      else { progress.set(0, "Failed."); toast(msg, "err"); }
    } finally {
      un();
      running = false;
      stopBtn.disabled = true;
      refresh();
    }
  }

  const revealBtn = h("button", { class: "btn ghost", style: "display:none", onclick: () => lastOutput && reveal(lastOutput) }, "Show in folder");
  startBtn.addEventListener("click", start);
  stopBtn.addEventListener("click", () => cancel());

  const el = h("div", { class: "view" },
    // 1 · Add
    h("div", { class: "card" },
      h("h2", {}, h("span", { class: "step" }, "1"), "Add Videos"),
      dropzone,
    ),
    // 2 · List
    h("div", { class: "card" },
      h("h2", {}, h("span", { class: "step" }, "2"), "Review & Reorder"),
      h("div", { class: "list-head" },
        h("div", { style: "text-align:center" }, "#"), h("div"), h("div", {}, "File"), h("div", { class: "dur" }, "Length"), h("div")),
      listEl,
      h("div", { class: "row", style: "margin-top:10px;justify-content:space-between" },
        h("div", { class: "toolbar" },
          h("button", { class: "btn ghost", onclick: () => files.moveActive(-1) }, "↑ Up"),
          h("button", { class: "btn ghost", onclick: () => files.moveActive(1) }, "↓ Down"),
          h("button", { class: "btn ghost", onclick: () => files.selectAll(true) }, "Select all"),
          h("button", { class: "btn ghost", onclick: () => files.selectAll(false) }, "None"),
          h("button", { class: "btn ghost", onclick: () => files.clearAll() }, "Clear"),
        ),
        totalEl,
      ),
    ),
    // 3 · Output
    h("div", { class: "card" },
      h("h2", {}, h("span", { class: "step" }, "3"), "Output"),
      h("div", { class: "field" },
        h("label", {}, "File name"),
        h("div", { class: "row" }, nameInput, extSelect, renameBtn),
        renamePreview,
      ),
      h("div", { class: "field", style: "margin-top:10px" },
        h("label", {}, "Save to"),
        h("div", { class: "row" }, dirInput,
          h("button", { class: "btn", onclick: async () => { const d = await pickFolder(); if (d) { dirInput.value = d; refresh(); } } }, "Browse…")),
      ),
    ),
    // 4 · Options
    h("div", { class: "card" },
      h("h2", {}, h("span", { class: "step" }, "4"), "Options"),
      h("label", { class: "row", style: "cursor:pointer" }, delChk,
        h("span", {}, "Delete original files after a successful merge")),
      h("div", { class: "hint", style: "margin-top:4px;margin-left:27px" }, "⚠ Permanent — originals cannot be recovered."),
    ),
    // 5 · Run
    h("div", { class: "card" },
      h("h2", {}, h("span", { class: "step" }, "5"), "Run"),
      h("div", { class: "row", style: "margin-bottom:14px" }, startBtn, stopBtn, revealBtn),
      progress.root,
    ),
  );

  return { el, onDrop: addFiles };
}
