import { initI18n, t, tDyn } from "./i18n";
import { initSidebar } from "./sidebar";
import { projectIndent } from "./project-indent";

interface Project {
  id: string;
  reference?: string | null;
  title: string;
  path: string;
}

let allProjects: Project[] = [];

function esc(s: string): string {
  const d = document.createElement("div");
  d.textContent = s;
  return d.innerHTML;
}

async function loadProjects() {
  try {
    const resp = await fetch("/api/projects");
    if (resp.ok) allProjects = await resp.json();
  } catch {
    /* non-fatal */
  }
}

function populateProjects() {
  const sel = document.getElementById("appointment-project") as HTMLSelectElement;
  const opts: string[] = [
    `<option value="">${esc(t("appointments.field.akte.none"))}</option>`,
  ];
  for (const a of allProjects) {
    const indent = projectIndent(a.path);
    opts.push(
      `<option value="${esc(a.id)}">${indent}${esc(a.reference || "")} — ${esc(a.title)}</option>`,
    );
  }
  sel.innerHTML = opts.join("");

  const params = new URLSearchParams(window.location.search);
  const ak = params.get("project_id");
  if (ak) sel.value = ak;
}

function preFillStart() {
  const start = document.getElementById("appointment-start") as HTMLInputElement;
  const now = new Date();
  now.setMinutes(now.getMinutes() + (15 - (now.getMinutes() % 15)));
  now.setSeconds(0);
  now.setMilliseconds(0);
  const pad = (n: number) => String(n).padStart(2, "0");
  start.value = `${now.getFullYear()}-${pad(now.getMonth() + 1)}-${pad(now.getDate())}T${pad(now.getHours())}:${pad(now.getMinutes())}`;
}

async function submitForm(ev: Event) {
  ev.preventDefault();
  const msg = document.getElementById("appointment-new-msg")!;
  const submitBtn = (ev.target as HTMLFormElement).querySelector<HTMLButtonElement>("button[type=submit]")!;
  msg.textContent = "";

  const title = (document.getElementById("appointment-title") as HTMLInputElement).value.trim();
  const startRaw = (document.getElementById("appointment-start") as HTMLInputElement).value;
  const endRaw = (document.getElementById("appointment-end") as HTMLInputElement).value;
  const type = (document.getElementById("appointment-type") as HTMLSelectElement).value;
  const projectID = (document.getElementById("appointment-project") as HTMLSelectElement).value;
  const location = (document.getElementById("appointment-location") as HTMLInputElement).value.trim();
  const description = (document.getElementById("appointment-description") as HTMLTextAreaElement).value.trim();

  if (!title || !startRaw) {
    msg.textContent = t("appointments.error.required");
    msg.className = "form-msg form-msg-error";
    return;
  }

  const payload: Record<string, unknown> = {
    title,
    start_at: new Date(startRaw).toISOString(),
  };
  if (endRaw) payload.end_at = new Date(endRaw).toISOString();
  if (type) payload.appointment_type = type;
  if (projectID) payload.project_id = projectID;
  if (location) payload.location = location;
  if (description) payload.description = description;

  submitBtn.disabled = true;
  try {
    const resp = await fetch("/api/appointments", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify(payload),
    });
    if (resp.ok) {
      const created = await resp.json();
      window.location.href = `/appointments/${created.id}`;
      return;
    }
    const data = await resp.json().catch(() => ({}) as { error?: string });
    msg.textContent = data.error || t("appointments.error.generic");
    msg.className = "form-msg form-msg-error";
  } catch {
    msg.textContent = t("appointments.error.generic");
    msg.className = "form-msg form-msg-error";
  } finally {
    submitBtn.disabled = false;
  }
}

// t-paliad-154 — form-time 4-eye hint, mirroring deadlines-new.ts.
async function refreshApprovalHint(): Promise<void> {
  const hint = document.getElementById("appointment-approval-hint");
  const text = document.getElementById("appointment-approval-hint-text");
  if (!hint || !text) return;
  const projectID = (document.getElementById("appointment-project") as HTMLSelectElement | null)?.value || "";
  if (!projectID) {
    hint.style.display = "none";
    return;
  }
  try {
    const resp = await fetch(
      `/api/projects/${encodeURIComponent(projectID)}/approval-policies/effective?entity_type=appointment&lifecycle=create`,
      { credentials: "include" },
    );
    if (!resp.ok) {
      hint.style.display = "none";
      return;
    }
    // t-paliad-160 split-grammar — read requires_approval + min_role.
    // Fall back to the legacy required_role mirror (M1 dual-read window
    // only — drops in M2).
    const eff = await resp.json() as {
      requires_approval?: boolean;
      min_role?: string | null;
      required_role?: string | null;
      source?: string | null;
      source_name?: string | null;
    };
    const role = eff.min_role || eff.required_role || null;
    const required = (eff.requires_approval === true) || (role !== null && role !== "none");
    if (!required || !role) {
      hint.style.display = "none";
      return;
    }
    const roleLabel = tDyn("admin.approval_policies.role." + role) || role;
    const sourceLabel = eff.source_name
      ? ` · ${tDyn("admin.approval_policies.source." + (eff.source || "")) || ""}: ${eff.source_name}`
      : "";
    text.textContent = (t("appointments.form.approval_hint") || "4-Augen-Prüfung erforderlich")
      + ` · ${roleLabel}${sourceLabel}`;
    hint.style.display = "";
  } catch {
    hint.style.display = "none";
  }
}

document.addEventListener("DOMContentLoaded", async () => {
  initI18n();
  initSidebar();
  await loadProjects();
  populateProjects();
  preFillStart();
  document.getElementById("appointment-new-form")!.addEventListener("submit", submitForm);
  void refreshApprovalHint();
  document.getElementById("appointment-project")?.addEventListener("change", () => {
    void refreshApprovalHint();
  });
});
