import { initI18n, t, getLang } from "./i18n";
import { initSidebar } from "./sidebar";

function isEN(): boolean { return getLang() === "en"; }

// /admin/submission-building-blocks — Composer building-blocks admin
// editor (t-paliad-315 Slice C). Three-pane layout: list → editor →
// version log. CRUD via /api/admin/submission-building-blocks/*.
//
// Per Q2 ratification (m, 2026-05-26): building blocks are plain text
// paste sources. The editor here is curator-only — no per-section
// lineage to surface, no "where is this block used" view.

interface BuildingBlockJSON {
  id: string;
  slug: string;
  firm?: string | null;
  section_key: string;
  proceeding_family?: string | null;
  title_de: string;
  title_en: string;
  description_de?: string | null;
  description_en?: string | null;
  content_md_de: string;
  content_md_en: string;
  author_id?: string | null;
  visibility: string;
  is_published: boolean;
  created_at: string;
  updated_at: string;
}

interface VersionJSON {
  id: string;
  building_block_id: string;
  content_md_de: string;
  content_md_en: string;
  title_de: string;
  title_en: string;
  edited_by?: string | null;
  note?: string | null;
  created_at: string;
}

const VISIBILITIES = ["private", "team", "firm", "global"];

// Section keys must match what the Composer base spec declares for
// each section (see internal/db/migrations/146_submission_bases.up.sql).
const SECTION_KEYS = [
  "letterhead", "caption", "introduction", "requests",
  "facts", "legal_argument", "evidence", "exhibits",
  "closing", "signature",
];

const state = {
  blocks: [] as BuildingBlockJSON[],
  selectedID: null as string | null,
  versions: [] as VersionJSON[],
  dirty: false,
};

async function boot(): Promise<void> {
  initI18n();
  initSidebar();
  await loadList();
  document.getElementById("admin-bb-new-btn")?.addEventListener("click", onNew);
}

async function loadList(): Promise<void> {
  try {
    const res = await fetch("/api/admin/submission-building-blocks", { credentials: "include" });
    if (!res.ok) {
      feedback(`HTTP ${res.status}`, true);
      return;
    }
    const body = await res.json() as { blocks?: BuildingBlockJSON[] };
    state.blocks = body.blocks ?? [];
    paintList();
  } catch (err) {
    feedback(String(err), true);
  }
}

function paintList(): void {
  const host = document.getElementById("admin-bb-list");
  if (!host) return;
  host.innerHTML = "";
  if (state.blocks.length === 0) {
    const empty = document.createElement("p");
    empty.className = "admin-bb-empty";
    empty.textContent = isEN() ? "No blocks yet." : "Noch keine Bausteine.";
    host.appendChild(empty);
    return;
  }
  for (const b of state.blocks) {
    const row = document.createElement("button");
    row.type = "button";
    row.className = "admin-bb-list-row";
    if (b.id === state.selectedID) row.classList.add("admin-bb-list-row--active");
    const title = isEN() ? b.title_en : b.title_de;
    row.innerHTML = `
      <span class="admin-bb-list-title">${escapeHTML(title || b.slug)}</span>
      <span class="admin-bb-list-meta">
        <span class="admin-bb-list-section">${escapeHTML(b.section_key)}</span>
        <span class="admin-bb-list-vis admin-bb-list-vis--${escapeHTML(b.visibility)}">${escapeHTML(b.visibility)}</span>
        ${b.is_published ? "" : `<span class="admin-bb-list-draft">${isEN() ? "draft" : "Entwurf"}</span>`}
      </span>`;
    row.addEventListener("click", () => onSelect(b.id));
    host.appendChild(row);
  }
}

async function onSelect(id: string): Promise<void> {
  state.selectedID = id;
  state.dirty = false;
  paintList();
  const b = state.blocks.find(x => x.id === id);
  if (!b) return;
  paintEditor(b);
  await loadVersions(id);
}

function onNew(): void {
  state.selectedID = null;
  state.versions = [];
  state.dirty = false;
  paintList();
  paintEditor(null);
  paintVersions();
}

function paintEditor(b: BuildingBlockJSON | null): void {
  const host = document.getElementById("admin-bb-editor");
  if (!host) return;
  const isNew = b === null;
  const data = b ?? {
    id: "",
    slug: "",
    firm: "",
    section_key: "requests",
    proceeding_family: "",
    title_de: "",
    title_en: "",
    description_de: "",
    description_en: "",
    content_md_de: "",
    content_md_en: "",
    visibility: "firm",
    is_published: false,
  } as Partial<BuildingBlockJSON>;

  host.innerHTML = "";
  const form = document.createElement("form");
  form.className = "admin-bb-form";
  form.addEventListener("submit", (e) => { e.preventDefault(); onSave(isNew); });

  form.appendChild(textField("slug", isEN() ? "Slug" : "Slug", data.slug ?? "", true));
  form.appendChild(textField("firm", "Firm", data.firm ?? "", false, isEN() ? "leer = firmenagnostisch" : "leer = firmenagnostisch"));
  form.appendChild(selectField("section_key", isEN() ? "Section key" : "Abschnitts-Slug", data.section_key ?? "requests", SECTION_KEYS, false));
  form.appendChild(textField("proceeding_family", isEN() ? "Proceeding family" : "Verfahrensfamilie", data.proceeding_family ?? "", false, "z. B. de.inf.lg"));
  form.appendChild(textField("title_de", "Titel (DE)", data.title_de ?? "", true));
  form.appendChild(textField("title_en", "Title (EN)", data.title_en ?? "", true));
  form.appendChild(textareaField("description_de", "Beschreibung (DE)", data.description_de ?? "", 2));
  form.appendChild(textareaField("description_en", "Description (EN)", data.description_en ?? "", 2));
  form.appendChild(textareaField("content_md_de", isEN() ? "Content (DE Markdown)" : "Inhalt (DE Markdown)", data.content_md_de ?? "", 10));
  form.appendChild(textareaField("content_md_en", isEN() ? "Content (EN Markdown)" : "Inhalt (EN Markdown)", data.content_md_en ?? "", 10));
  form.appendChild(selectField("visibility", isEN() ? "Visibility" : "Sichtbarkeit", data.visibility ?? "firm", VISIBILITIES, false));
  form.appendChild(checkboxField("is_published", isEN() ? "Published" : "Veröffentlicht", Boolean(data.is_published)));

  if (!isNew) {
    form.appendChild(textField("note", isEN() ? "Save note (optional)" : "Speicher-Notiz (optional)", "", false));
  }

  const actions = document.createElement("div");
  actions.className = "admin-bb-form-actions";

  const save = document.createElement("button");
  save.type = "submit";
  save.className = "btn-primary btn-cta-lime";
  save.textContent = isEN() ? "Save" : "Speichern";
  actions.appendChild(save);

  if (!isNew) {
    const del = document.createElement("button");
    del.type = "button";
    del.className = "btn-link-danger";
    del.textContent = isEN() ? "Delete" : "Löschen";
    del.addEventListener("click", () => onDelete());
    actions.appendChild(del);
  }
  form.appendChild(actions);
  host.appendChild(form);
}

function textField(name: string, label: string, value: string, required: boolean, hint?: string): HTMLElement {
  const wrap = document.createElement("label");
  wrap.className = "admin-bb-form-row";
  const lab = document.createElement("span");
  lab.textContent = label + (required ? " *" : "");
  wrap.appendChild(lab);
  const input = document.createElement("input");
  input.type = "text";
  input.name = name;
  input.className = "entity-form-input";
  input.value = value;
  if (required) input.required = true;
  wrap.appendChild(input);
  if (hint) {
    const h = document.createElement("small");
    h.className = "admin-bb-form-hint";
    h.textContent = hint;
    wrap.appendChild(h);
  }
  return wrap;
}

function textareaField(name: string, label: string, value: string, rows: number): HTMLElement {
  const wrap = document.createElement("label");
  wrap.className = "admin-bb-form-row";
  const lab = document.createElement("span");
  lab.textContent = label;
  wrap.appendChild(lab);
  const ta = document.createElement("textarea");
  ta.name = name;
  ta.className = "entity-form-input";
  ta.rows = rows;
  ta.value = value;
  wrap.appendChild(ta);
  return wrap;
}

function selectField(name: string, label: string, value: string, options: string[], required: boolean): HTMLElement {
  const wrap = document.createElement("label");
  wrap.className = "admin-bb-form-row";
  const lab = document.createElement("span");
  lab.textContent = label + (required ? " *" : "");
  wrap.appendChild(lab);
  const sel = document.createElement("select");
  sel.name = name;
  sel.className = "entity-form-input";
  for (const opt of options) {
    const o = document.createElement("option");
    o.value = opt;
    o.textContent = opt;
    if (opt === value) o.selected = true;
    sel.appendChild(o);
  }
  wrap.appendChild(sel);
  return wrap;
}

function checkboxField(name: string, label: string, value: boolean): HTMLElement {
  const wrap = document.createElement("label");
  wrap.className = "admin-bb-form-row admin-bb-form-row--checkbox";
  const input = document.createElement("input");
  input.type = "checkbox";
  input.name = name;
  input.checked = value;
  wrap.appendChild(input);
  const lab = document.createElement("span");
  lab.textContent = label;
  wrap.appendChild(lab);
  return wrap;
}

async function onSave(isNew: boolean): Promise<void> {
  const form = document.querySelector(".admin-bb-form") as HTMLFormElement | null;
  if (!form) return;
  const data = new FormData(form);
  const payload: Record<string, unknown> = {};
  for (const key of ["slug", "section_key", "title_de", "title_en", "content_md_de", "content_md_en", "visibility"]) {
    const v = data.get(key);
    if (v !== null) payload[key] = String(v);
  }
  for (const key of ["firm", "proceeding_family", "description_de", "description_en"]) {
    const v = data.get(key);
    if (v !== null) {
      const s = String(v).trim();
      payload[key] = s === "" ? null : s;
    }
  }
  payload.is_published = (data.get("is_published") === "on");
  if (!isNew) {
    const note = data.get("note");
    if (note) payload.note = String(note);
  }
  try {
    const url = isNew
      ? "/api/admin/submission-building-blocks"
      : `/api/admin/submission-building-blocks/${state.selectedID}`;
    const method = isNew ? "POST" : "PATCH";
    const res = await fetch(url, {
      method,
      credentials: "include",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify(payload),
    });
    if (!res.ok) {
      const body = await res.json().catch(() => ({} as { error?: string }));
      feedback(body.error ?? `HTTP ${res.status}`, true);
      return;
    }
    const saved = await res.json() as BuildingBlockJSON;
    feedback(isEN() ? "Saved." : "Gespeichert.", false);
    await loadList();
    state.selectedID = saved.id;
    paintList();
    paintEditor(saved);
    await loadVersions(saved.id);
  } catch (err) {
    feedback(String(err), true);
  }
}

async function onDelete(): Promise<void> {
  if (!state.selectedID) return;
  const sure = confirm(isEN() ? "Delete this block?" : "Diesen Baustein löschen?");
  if (!sure) return;
  try {
    const res = await fetch(`/api/admin/submission-building-blocks/${state.selectedID}`, {
      method: "DELETE",
      credentials: "include",
    });
    if (!res.ok && res.status !== 204) {
      feedback(`HTTP ${res.status}`, true);
      return;
    }
    feedback(isEN() ? "Deleted." : "Gelöscht.", false);
    state.selectedID = null;
    await loadList();
    paintEditor(null);
    state.versions = [];
    paintVersions();
  } catch (err) {
    feedback(String(err), true);
  }
}

async function loadVersions(blockID: string): Promise<void> {
  try {
    const res = await fetch(`/api/admin/submission-building-blocks/${blockID}/versions`, { credentials: "include" });
    if (!res.ok) {
      state.versions = [];
      paintVersions();
      return;
    }
    const body = await res.json() as { versions?: VersionJSON[] };
    state.versions = body.versions ?? [];
    paintVersions();
  } catch {
    state.versions = [];
    paintVersions();
  }
}

function paintVersions(): void {
  const host = document.getElementById("admin-bb-versions");
  if (!host) return;
  host.innerHTML = "";
  if (state.versions.length === 0) return;
  const h = document.createElement("h3");
  h.textContent = isEN() ? "History" : "Verlauf";
  host.appendChild(h);
  for (const v of state.versions) {
    const row = document.createElement("div");
    row.className = "admin-bb-version-row";
    const date = new Date(v.created_at).toLocaleString();
    row.innerHTML = `
      <div class="admin-bb-version-meta">${escapeHTML(date)} — ${escapeHTML(v.note ?? "")}</div>`;
    const btn = document.createElement("button");
    btn.type = "button";
    btn.className = "btn-small btn-secondary";
    btn.textContent = isEN() ? "Restore" : "Wiederherstellen";
    btn.addEventListener("click", () => onRestore(v.id));
    row.appendChild(btn);
    host.appendChild(row);
  }
}

async function onRestore(versionID: string): Promise<void> {
  if (!state.selectedID) return;
  try {
    const res = await fetch(
      `/api/admin/submission-building-blocks/${state.selectedID}/restore/${versionID}`,
      { method: "POST", credentials: "include" },
    );
    if (!res.ok) {
      feedback(`HTTP ${res.status}`, true);
      return;
    }
    const restored = await res.json() as BuildingBlockJSON;
    feedback(isEN() ? "Restored." : "Wiederhergestellt.", false);
    paintEditor(restored);
    await loadVersions(restored.id);
    await loadList();
  } catch (err) {
    feedback(String(err), true);
  }
}

function feedback(msg: string, isError: boolean): void {
  const host = document.getElementById("admin-bb-feedback");
  if (!host) return;
  host.style.display = "";
  host.className = "form-msg " + (isError ? "form-msg--error" : "form-msg--ok");
  host.textContent = msg;
  if (!isError) {
    setTimeout(() => { host.style.display = "none"; }, 3000);
  }
}

function escapeHTML(s: string): string {
  return s
    .replace(/&/g, "&amp;")
    .replace(/</g, "&lt;")
    .replace(/>/g, "&gt;")
    .replace(/"/g, "&quot;")
    .replace(/'/g, "&#39;");
}

// Silence unused-import warning when t() isn't called directly — i18n
// is initialised so data-i18n attrs render on first paint.
void t;

if (document.readyState === "loading") {
  document.addEventListener("DOMContentLoaded", boot);
} else {
  void boot();
}
