// Litigation Builder — promote-to-project wizard (m/paliad#153 PRD §2.4
// + §5.4, B5).
//
// 3 steps: Bestätigen (read-only summary) → Parteien ergänzen (party
// names) → Akte-Metadaten (title, reference, case number, our_side,
// litigation parent, team). Commit POSTs the merged payload to
// /api/builder/scenarios/{id}/promote — a single server-side transaction
// (no partial promotions) that creates the paliad.projects 'case' row,
// cascades deadlines, and flips the scenario to 'promoted'. On success
// the wizard navigates to /projects/{new-id}.

import { t } from "./i18n";

interface ProjectOption {
  id: string;
  title: string;
  type: string;
  reference?: string;
}

interface UserOption {
  id: string;
  email: string;
  display_name?: string;
  office?: string;
}

interface PartyRow {
  name: string;
  role: string;
  representative: string;
}

export interface PromoteContext {
  scenarioId: string;
  ownerId?: string;
  proceedingLabel: string;
  filedCount: number;
  plannedCount: number;
  flagCount: number;
  extraTopLevel: number;
  defaultOurSide: "claimant" | "defendant" | null;
  defaultTitle: string;
  onSuccess: (projectId: string) => void;
}

export async function openPromoteWizard(ctx: PromoteContext): Promise<void> {
  // Parallel fetch: litigation parents + HLC users (both optional pickers).
  const [parents, users] = await Promise.all([
    fetchProjects("litigation"),
    fetchUsers(),
  ]);

  let step = 1;
  const parties: PartyRow[] = [];
  const meta = {
    title: ctx.defaultTitle || "",
    reference: "",
    caseNumber: "",
    clientNumber: "",
    ourSide: (ctx.defaultOurSide ?? "") as "" | "claimant" | "defendant",
    parentId: "",
    teamIds: new Set<string>(),
  };

  const backdrop = document.createElement("div");
  backdrop.className = "builder-modal-backdrop";
  const modal = document.createElement("div");
  modal.className = "builder-modal builder-promote-modal";
  modal.setAttribute("role", "dialog");
  modal.setAttribute("aria-modal", "true");
  modal.setAttribute("aria-label", t("builder.promote.title"));
  backdrop.appendChild(modal);

  const close = () => {
    document.removeEventListener("keydown", onEsc, true);
    backdrop.remove();
  };
  const onEsc = (e: KeyboardEvent) => {
    if (e.key === "Escape") close();
  };
  backdrop.addEventListener("click", (e) => {
    if (e.target === backdrop) close();
  });
  document.addEventListener("keydown", onEsc, true);

  function stepHeader(): string {
    const steps = [
      t("builder.promote.step1"),
      t("builder.promote.step2"),
      t("builder.promote.step3"),
    ];
    const dots = steps.map((label, i) => {
      const n = i + 1;
      const cls = n === step ? " is-active" : n < step ? " is-done" : "";
      return `<li class="builder-promote-step${cls}"><span class="builder-promote-step-n">${n}</span>` +
        `<span class="builder-promote-step-label">${escHtml(label)}</span></li>`;
    }).join("");
    return `<ol class="builder-promote-steps">${dots}</ol>`;
  }

  function renderStep1(): string {
    const rows = [
      `<li><span>${escHtml(t("builder.promote.summary.proceeding"))}</span><strong>${escHtml(ctx.proceedingLabel)}</strong></li>`,
      `<li><span>${escHtml(t("builder.promote.summary.events_filed"))}</span><strong>${ctx.filedCount}</strong></li>`,
      `<li><span>${escHtml(t("builder.promote.summary.events_planned"))}</span><strong>${ctx.plannedCount}</strong></li>`,
      `<li><span>${escHtml(t("builder.promote.summary.flags"))}</span><strong>${ctx.flagCount}</strong></li>`,
    ].join("");
    const extra = ctx.extraTopLevel > 0
      ? `<p class="builder-promote-note">${escHtml(
          t("builder.promote.summary.note_extra").replace("{n}", String(ctx.extraTopLevel)),
        )}</p>`
      : "";
    return (
      `<h3 class="builder-promote-section-title">${escHtml(t("builder.promote.summary.heading"))}</h3>` +
      `<ul class="builder-promote-summary">${rows}</ul>${extra}`
    );
  }

  function renderStep2(): string {
    const list = parties.length === 0
      ? `<p class="builder-promote-empty">${escHtml(t("builder.promote.parties.empty"))}</p>`
      : parties.map((p, i) => (
          `<div class="builder-promote-party" data-idx="${i}">` +
          `<input class="builder-promote-party-name" placeholder="${escAttr(t("builder.promote.parties.name"))}" value="${escAttr(p.name)}" />` +
          `<input class="builder-promote-party-role" placeholder="${escAttr(t("builder.promote.parties.role"))}" value="${escAttr(p.role)}" />` +
          `<input class="builder-promote-party-rep" placeholder="${escAttr(t("builder.promote.parties.representative"))}" value="${escAttr(p.representative)}" />` +
          `<button type="button" class="builder-promote-party-remove" aria-label="${escAttr(t("builder.promote.parties.remove"))}">×</button>` +
          `</div>`
        )).join("");
    return (
      `<p class="builder-promote-hint">${escHtml(t("builder.promote.parties.hint"))}</p>` +
      `<div class="builder-promote-parties">${list}</div>` +
      `<button type="button" class="builder-promote-party-add">${escHtml(t("builder.promote.parties.add"))}</button>`
    );
  }

  function renderStep3(): string {
    const parentOpts = [`<option value="">${escHtml(t("builder.promote.meta.parent.none"))}</option>`]
      .concat(parents.map((p) => {
        const sel = p.id === meta.parentId ? " selected" : "";
        const label = p.reference ? `${p.title} (${p.reference})` : p.title;
        return `<option value="${escAttr(p.id)}"${sel}>${escHtml(label)}</option>`;
      })).join("");
    const sideSel = (v: string) => (meta.ourSide === v ? " selected" : "");
    const team = users
      .filter((u) => u.id !== ctx.ownerId)
      .slice(0, 40)
      .map((u) => {
        const checked = meta.teamIds.has(u.id) ? " checked" : "";
        const label = (u.display_name || "").trim()
          ? ((u.office ? `${u.display_name} · ${u.office}` : u.display_name) as string)
          : u.email;
        return (
          `<label class="builder-promote-team-item">` +
          `<input type="checkbox" class="builder-promote-team-cb" data-user-id="${escAttr(u.id)}"${checked} />` +
          `<span>${escHtml(label)}</span></label>`
        );
      }).join("");
    return (
      `<label class="builder-promote-field"><span>${escHtml(t("builder.promote.meta.title"))}</span>` +
      `<input class="builder-promote-title" placeholder="${escAttr(t("builder.promote.meta.title.placeholder"))}" value="${escAttr(meta.title)}" /></label>` +
      `<div class="builder-promote-field-row">` +
      `<label class="builder-promote-field"><span>${escHtml(t("builder.promote.meta.reference"))}</span>` +
      `<input class="builder-promote-reference" value="${escAttr(meta.reference)}" /></label>` +
      `<label class="builder-promote-field"><span>${escHtml(t("builder.promote.meta.case_number"))}</span>` +
      `<input class="builder-promote-casenumber" value="${escAttr(meta.caseNumber)}" /></label>` +
      `</div>` +
      `<div class="builder-promote-field-row">` +
      `<label class="builder-promote-field"><span>${escHtml(t("builder.promote.meta.client_number"))}</span>` +
      `<input class="builder-promote-clientnumber" value="${escAttr(meta.clientNumber)}" /></label>` +
      `<label class="builder-promote-field"><span>${escHtml(t("builder.promote.meta.our_side"))}</span>` +
      `<select class="builder-promote-ourside">` +
      `<option value=""${sideSel("")}>${escHtml(t("builder.promote.meta.our_side.none"))}</option>` +
      `<option value="claimant"${sideSel("claimant")}>${escHtml(t("builder.promote.meta.our_side.claimant"))}</option>` +
      `<option value="defendant"${sideSel("defendant")}>${escHtml(t("builder.promote.meta.our_side.defendant"))}</option>` +
      `</select></label>` +
      `</div>` +
      `<label class="builder-promote-field"><span>${escHtml(t("builder.promote.meta.parent"))}</span>` +
      `<select class="builder-promote-parent">${parentOpts}</select></label>` +
      `<div class="builder-promote-field"><span>${escHtml(t("builder.promote.meta.team"))}</span>` +
      `<p class="builder-promote-team-hint">${escHtml(t("builder.promote.meta.team.hint"))}</p>` +
      `<div class="builder-promote-team">${team}</div></div>` +
      `<p class="builder-promote-error" hidden></p>`
    );
  }

  function render(): void {
    let body = "";
    if (step === 1) body = renderStep1();
    else if (step === 2) body = renderStep2();
    else body = renderStep3();

    const backLabel = t("builder.promote.back");
    const cancelLabel = t("builder.promote.cancel");
    const nextLabel = step < 3 ? t("builder.promote.next") : t("builder.promote.commit");

    modal.innerHTML = `
      <header class="builder-modal-header">
        <h2 class="builder-modal-title">${escHtml(t("builder.promote.title"))}</h2>
        <button type="button" class="builder-modal-close" aria-label="${escAttr(cancelLabel)}">×</button>
      </header>
      ${stepHeader()}
      <div class="builder-promote-body">${body}</div>
      <footer class="builder-promote-footer">
        <button type="button" class="builder-promote-cancel">${escHtml(cancelLabel)}</button>
        <span class="builder-promote-footer-spacer"></span>
        ${step > 1 ? `<button type="button" class="builder-promote-backbtn">${escHtml(backLabel)}</button>` : ""}
        <button type="button" class="builder-promote-nextbtn builder-action-btn--primary">${escHtml(nextLabel)}</button>
      </footer>`;
    wire();
  }

  function captureStep2(): void {
    modal.querySelectorAll<HTMLElement>(".builder-promote-party").forEach((row) => {
      const idx = Number(row.getAttribute("data-idx"));
      if (Number.isNaN(idx) || !parties[idx]) return;
      parties[idx].name = (row.querySelector(".builder-promote-party-name") as HTMLInputElement).value;
      parties[idx].role = (row.querySelector(".builder-promote-party-role") as HTMLInputElement).value;
      parties[idx].representative = (row.querySelector(".builder-promote-party-rep") as HTMLInputElement).value;
    });
  }

  function captureStep3(): void {
    const get = (sel: string) => (modal.querySelector(sel) as HTMLInputElement | null)?.value ?? "";
    meta.title = get(".builder-promote-title");
    meta.reference = get(".builder-promote-reference");
    meta.caseNumber = get(".builder-promote-casenumber");
    meta.clientNumber = get(".builder-promote-clientnumber");
    meta.ourSide = ((modal.querySelector(".builder-promote-ourside") as HTMLSelectElement)?.value || "") as typeof meta.ourSide;
    meta.parentId = (modal.querySelector(".builder-promote-parent") as HTMLSelectElement)?.value || "";
    meta.teamIds = new Set(
      Array.from(modal.querySelectorAll<HTMLInputElement>(".builder-promote-team-cb:checked"))
        .map((cb) => cb.getAttribute("data-user-id") || "")
        .filter(Boolean),
    );
  }

  function wire(): void {
    modal.querySelector(".builder-modal-close")?.addEventListener("click", close);
    modal.querySelector(".builder-promote-cancel")?.addEventListener("click", close);
    modal.querySelector(".builder-promote-backbtn")?.addEventListener("click", () => {
      if (step === 2) captureStep2();
      if (step === 3) captureStep3();
      step = Math.max(1, step - 1);
      render();
    });
    modal.querySelector(".builder-promote-nextbtn")?.addEventListener("click", () => {
      if (step === 2) captureStep2();
      if (step < 3) {
        step += 1;
        render();
        return;
      }
      captureStep3();
      void commit();
    });
    if (step === 2) {
      modal.querySelector(".builder-promote-party-add")?.addEventListener("click", () => {
        captureStep2();
        parties.push({ name: "", role: "", representative: "" });
        render();
      });
      modal.querySelectorAll<HTMLElement>(".builder-promote-party-remove").forEach((btn) => {
        btn.addEventListener("click", () => {
          captureStep2();
          const row = btn.closest(".builder-promote-party") as HTMLElement;
          const idx = Number(row?.getAttribute("data-idx"));
          if (!Number.isNaN(idx)) parties.splice(idx, 1);
          render();
        });
      });
    }
  }

  async function commit(): Promise<void> {
    const errEl = modal.querySelector(".builder-promote-error") as HTMLElement | null;
    const showErr = (msg: string) => {
      if (errEl) {
        errEl.textContent = msg;
        errEl.hidden = false;
      }
    };
    if (!meta.title.trim()) {
      showErr(t("builder.promote.error.title_required"));
      return;
    }
    const nextBtn = modal.querySelector(".builder-promote-nextbtn") as HTMLButtonElement | null;
    if (nextBtn) nextBtn.disabled = true;

    const payload: Record<string, unknown> = {
      title: meta.title.trim(),
      reference: meta.reference.trim() || undefined,
      case_number: meta.caseNumber.trim() || undefined,
      client_number: meta.clientNumber.trim() || undefined,
      our_side: meta.ourSide || undefined,
      parent_id: meta.parentId || undefined,
      parties: parties
        .filter((p) => p.name.trim())
        .map((p) => ({
          name: p.name.trim(),
          role: p.role.trim() || undefined,
          representative: p.representative.trim() || undefined,
        })),
      team_members: Array.from(meta.teamIds).map((id) => ({ user_id: id })),
    };

    try {
      const resp = await fetch(
        "/api/builder/scenarios/" + encodeURIComponent(ctx.scenarioId) + "/promote",
        {
          method: "POST",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify(payload),
        },
      );
      if (!resp.ok) {
        if (nextBtn) nextBtn.disabled = false;
        showErr(t("builder.promote.error.generic"));
        return;
      }
      const out = (await resp.json()) as { project_id: string };
      const body = modal.querySelector(".builder-promote-body") as HTMLElement;
      if (body) body.innerHTML = `<p class="builder-promote-success">${escHtml(t("builder.promote.success"))}</p>`;
      ctx.onSuccess(out.project_id);
    } catch {
      if (nextBtn) nextBtn.disabled = false;
      showErr(t("builder.promote.error.generic"));
    }
  }

  render();
  document.body.appendChild(backdrop);
  (modal.querySelector(".builder-promote-nextbtn") as HTMLElement | null)?.focus();
}

async function fetchProjects(type: string): Promise<ProjectOption[]> {
  try {
    const resp = await fetch("/api/projects?type=" + encodeURIComponent(type));
    if (!resp.ok) return [];
    const data = (await resp.json()) as ProjectOption[];
    return Array.isArray(data) ? data : [];
  } catch {
    return [];
  }
}

async function fetchUsers(): Promise<UserOption[]> {
  try {
    const resp = await fetch("/api/users");
    if (!resp.ok) return [];
    const data = (await resp.json()) as UserOption[];
    return Array.isArray(data) ? data : [];
  } catch {
    return [];
  }
}

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

function escAttr(s: string): string {
  return s.replace(/&/g, "&amp;").replace(/"/g, "&quot;");
}
