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

// --- Types matching API response ---

interface FeeTableRow {
  streitwert: number;
  fee: number;
}

interface FeeVersionTable {
  version: string;
  label: string;
  validFrom: string;
  isCurrent: boolean;
  rows: FeeTableRow[];
}

interface UPCValueRow {
  maxValue: number | null;
  fee: number;
}

interface UPCRecoverRow {
  maxValue: number | null;
  ceiling: number;
}

interface UPCScheduleInfo {
  version: string;
  label: string;
  fixedInfringement: number;
  fixedRevocation: number;
  smeReduction: number;
  valueBased: UPCValueRow[];
  recoverableCosts: UPCRecoverRow[];
}

interface EPAFeeInfo {
  key: string;
  label: string;
  labelEN: string;
  fee: number;
  smeFee: number;
}

interface MultiplierInfo {
  key: string;
  label: string;
  labelEN: string;
  courtFeeFactor: number;
  feeBasis: string;
  raVGFactor: number;
  raTGFactor: number;
  paVGFactor: number;
  paTGFactor: number;
}

interface PatKostGCourtFee {
  key: string;
  label: string;
  labelEN: string;
  factor: number;
  note: string;
  noteEN: string;
}

interface DPMAFee {
  label: string;
  labelEN: string;
  fee: number;
}

interface DPMAAnnualFee {
  year: number;
  fee: number;
}

interface PatKostGInfo {
  courtFees: PatKostGCourtFee[];
  dpmaFees: DPMAFee[];
  annualFees: DPMAAnnualFee[];
}

interface FeeTableData {
  gkg: FeeVersionTable[];
  rvg: FeeVersionTable[];
  upc: UPCScheduleInfo[];
  epa: EPAFeeInfo[];
  multipliers: MultiplierInfo[];
  patkostg: PatKostGInfo;
}

interface LookupResult {
  streitwert: number;
  gkg: Record<string, number>;
  rvg: Record<string, number>;
  upc: Record<string, { fixedInfringement: number; valueBasedFee: number; total: number; smeTotal: number; recoverableCeiling: number }>;
}

// --- State ---

let data: FeeTableData | null = null;
let activeTab = "gkg";
let gkgVersion = "2025";
let rvgVersion = "2025";
let upcVersion = "2026";
let lookupStreitwert: number | null = null;
let lookupResult: LookupResult | null = null;

// --- Formatting ---

function fmtEUR(v: number): string {
  return v.toLocaleString("de-DE", { minimumFractionDigits: 2, maximumFractionDigits: 2 });
}

function fmtInt(v: number): string {
  return v.toLocaleString("de-DE", { maximumFractionDigits: 0 });
}

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

// --- Data loading ---

async function loadData() {
  const resp = await fetch("/api/tools/gebuehrentabellen");
  if (!resp.ok) return;
  data = await resp.json();
  renderAll();
}

async function doLookup(streitwert: number) {
  const resp = await fetch(`/api/tools/gebuehrentabellen/lookup?streitwert=${streitwert}`);
  if (!resp.ok) return;
  lookupResult = await resp.json();
  lookupStreitwert = streitwert;
  showLookupResult();
  renderActivePanel();
}

// --- Render all ---

function renderAll() {
  if (!data) return;
  renderVersionPills("gkg-versions", data.gkg, gkgVersion, (v) => { gkgVersion = v; renderGKG(); });
  renderVersionPills("rvg-versions", data.rvg, rvgVersion, (v) => { rvgVersion = v; renderRVG(); });
  renderUPCVersionPills();
  renderGKG();
  renderRVG();
  renderUPC();
  renderEPA();
  renderPatKostG();
  renderMultipliers();
}

function renderActivePanel() {
  if (!data) return;
  switch (activeTab) {
    case "gkg": renderGKG(); break;
    case "rvg": renderRVG(); break;
    case "upc": renderUPC(); break;
  }
}

// --- Version pills ---

function renderVersionPills(
  containerId: string,
  versions: FeeVersionTable[],
  activeVersion: string,
  onSelect: (v: string) => void
) {
  const container = document.getElementById(containerId)!;
  container.innerHTML = versions.map((v) => {
    const label = v.isCurrent ? `${v.version} (${t("gebuehren.current")})` : v.version;
    const cls = v.version === activeVersion ? "filter-pill active" : "filter-pill";
    return `<button class="${cls}" data-version="${v.version}" type="button">${esc(label)}</button>`;
  }).join("");

  container.querySelectorAll<HTMLButtonElement>(".filter-pill").forEach((btn) => {
    btn.addEventListener("click", () => {
      container.querySelectorAll(".filter-pill").forEach((p) => p.classList.remove("active"));
      btn.classList.add("active");
      onSelect(btn.dataset.version!);
    });
  });
}

function renderUPCVersionPills() {
  if (!data) return;
  const container = document.getElementById("upc-versions")!;
  container.innerHTML = data.upc.map((s) => {
    const cls = s.version === upcVersion ? "filter-pill active" : "filter-pill";
    return `<button class="${cls}" data-version="${s.version}" type="button">${esc(s.label)}</button>`;
  }).join("");

  container.querySelectorAll<HTMLButtonElement>(".filter-pill").forEach((btn) => {
    btn.addEventListener("click", () => {
      container.querySelectorAll(".filter-pill").forEach((p) => p.classList.remove("active"));
      btn.classList.add("active");
      upcVersion = btn.dataset.version!;
      renderUPC();
    });
  });
}

// --- GKG / RVG table rendering ---

function renderFeeTable(tbodyId: string, versions: FeeVersionTable[], activeVersion: string, type: "gkg" | "rvg") {
  const tbody = document.getElementById(tbodyId)!;
  const table = versions.find((v) => v.version === activeVersion);
  if (!table) { tbody.innerHTML = ""; return; }

  const lookupFee = lookupResult && lookupResult[type] ? lookupResult[type][activeVersion] : null;
  const hasLookup = lookupStreitwert !== null && lookupFee !== null;

  let rows = table.rows;
  let insertedLookup = false;

  const html: string[] = [];
  for (let i = 0; i < rows.length; i++) {
    const row = rows[i];

    // Insert lookup row before the first row with streitwert >= lookupStreitwert
    if (hasLookup && !insertedLookup && lookupStreitwert! <= row.streitwert) {
      if (lookupStreitwert! === row.streitwert) {
        // Exact match — highlight this row
        html.push(`<tr class="highlight"><td>${fmtInt(row.streitwert)}</td><td>${fmtEUR(row.fee)}</td></tr>`);
        insertedLookup = true;
        continue;
      }
      // Insert custom row
      html.push(`<tr class="highlight"><td>${fmtInt(lookupStreitwert!)}</td><td>${fmtEUR(lookupFee!)}</td></tr>`);
      insertedLookup = true;
    }

    html.push(`<tr><td>${fmtInt(row.streitwert)}</td><td>${fmtEUR(row.fee)}</td></tr>`);
  }

  // Lookup streitwert exceeds all rows
  if (hasLookup && !insertedLookup) {
    html.push(`<tr class="highlight"><td>${fmtInt(lookupStreitwert!)}</td><td>${fmtEUR(lookupFee!)}</td></tr>`);
  }

  tbody.innerHTML = html.join("");

  // Scroll to highlighted row
  const highlighted = tbody.querySelector("tr.highlight");
  if (highlighted) {
    highlighted.scrollIntoView({ block: "center", behavior: "smooth" });
  }
}

function renderGKG() {
  if (!data) return;
  renderFeeTable("gkg-body", data.gkg, gkgVersion, "gkg");
}

function renderRVG() {
  if (!data) return;
  renderFeeTable("rvg-body", data.rvg, rvgVersion, "rvg");
}

// --- UPC ---

function renderUPC() {
  if (!data) return;
  const schedule = data.upc.find((s) => s.version === upcVersion);
  if (!schedule) return;

  const isEN = getLang() === "en";
  const smePercent = Math.round(schedule.smeReduction * 100);

  // Summary
  const summary = document.getElementById("upc-summary")!;
  summary.innerHTML = `<div class="gebuehren-upc-cards">
    <div class="gebuehren-upc-card">
      <div class="gebuehren-upc-card-label">${isEN ? "Fixed fee (infringement)" : "Festgebühr (Verletzung)"}</div>
      <div class="gebuehren-upc-card-value">${fmtEUR(schedule.fixedInfringement)}</div>
    </div>
    <div class="gebuehren-upc-card">
      <div class="gebuehren-upc-card-label">${isEN ? "Fixed fee (revocation)" : "Festgebühr (Nichtigkeit)"}</div>
      <div class="gebuehren-upc-card-value">${fmtEUR(schedule.fixedRevocation)}</div>
    </div>
    <div class="gebuehren-upc-card">
      <div class="gebuehren-upc-card-label">${isEN ? "SME reduction" : "KMU-Ermäßigung"}</div>
      <div class="gebuehren-upc-card-value">${smePercent}%</div>
    </div>
  </div>`;

  // Value-based table
  const valueBody = document.getElementById("upc-value-body")!;
  const upcLookup = lookupResult?.upc?.[upcVersion];

  valueBody.innerHTML = schedule.valueBased.map((row) => {
    const maxLabel = row.maxValue === null
      ? (isEN ? "unlimited" : "unbegrenzt")
      : fmtInt(row.maxValue);
    const isHighlighted = lookupStreitwert !== null && upcLookup &&
      ((row.maxValue === null && lookupStreitwert > (schedule.valueBased[schedule.valueBased.indexOf(row) - 1]?.maxValue ?? 0)) ||
       (row.maxValue !== null && lookupStreitwert <= row.maxValue &&
        (schedule.valueBased.indexOf(row) === 0 || lookupStreitwert > (schedule.valueBased[schedule.valueBased.indexOf(row) - 1]?.maxValue ?? 0))));
    return `<tr${isHighlighted ? ' class="highlight"' : ""}><td>${maxLabel}</td><td>${fmtEUR(row.fee)}</td></tr>`;
  }).join("");

  // Recoverable costs table
  const recoverBody = document.getElementById("upc-recover-body")!;
  recoverBody.innerHTML = schedule.recoverableCosts.map((row) => {
    const maxLabel = row.maxValue === null
      ? (isEN ? "unlimited" : "unbegrenzt")
      : fmtInt(row.maxValue);
    const isHighlighted = lookupStreitwert !== null && upcLookup &&
      ((row.maxValue === null && lookupStreitwert > (schedule.recoverableCosts[schedule.recoverableCosts.indexOf(row) - 1]?.maxValue ?? 0)) ||
       (row.maxValue !== null && lookupStreitwert <= row.maxValue &&
        (schedule.recoverableCosts.indexOf(row) === 0 || lookupStreitwert > (schedule.recoverableCosts[schedule.recoverableCosts.indexOf(row) - 1]?.maxValue ?? 0))));
    return `<tr${isHighlighted ? ' class="highlight"' : ""}><td>${maxLabel}</td><td>${fmtEUR(row.ceiling)}</td></tr>`;
  }).join("");

  // Scroll to highlighted
  const highlighted = valueBody.querySelector("tr.highlight") || recoverBody.querySelector("tr.highlight");
  if (highlighted) {
    highlighted.scrollIntoView({ block: "center", behavior: "smooth" });
  }
}

// --- EPA ---

function renderEPA() {
  if (!data) return;
  const isEN = getLang() === "en";
  const body = document.getElementById("epa-body")!;
  body.innerHTML = data.epa.map((fee) => {
    const label = isEN ? fee.labelEN : fee.label;
    const smeCol = fee.smeFee !== fee.fee
      ? fmtEUR(fee.smeFee)
      : '<span class="text-muted">\u2014</span>';
    return `<tr><td>${esc(label)}</td><td>${fmtEUR(fee.fee)}</td><td>${smeCol}</td></tr>`;
  }).join("");
}

// --- PatKostG ---

function renderPatKostG() {
  if (!data) return;
  const isEN = getLang() === "en";
  const pk = data.patkostg;

  // Court fees
  const courtBody = document.getElementById("patkostg-court-body")!;
  courtBody.innerHTML = pk.courtFees.map((f) => {
    const label = isEN ? f.labelEN : f.label;
    const note = isEN ? f.noteEN : f.note;
    return `<tr><td>${esc(label)}</td><td>${f.factor.toFixed(1)}x</td><td>${esc(note)}</td></tr>`;
  }).join("");

  // DPMA fees
  const dpmaBody = document.getElementById("patkostg-dpma-body")!;
  dpmaBody.innerHTML = pk.dpmaFees.map((f) => {
    const label = isEN ? f.labelEN : f.label;
    return `<tr><td>${esc(label)}</td><td>${fmtEUR(f.fee)}</td></tr>`;
  }).join("");

  // Annual fees
  const annualBody = document.getElementById("patkostg-annual-body")!;
  annualBody.innerHTML = pk.annualFees.map((f) => {
    const yearLabel = isEN ? `Year ${f.year}` : `${f.year}. Patentjahr`;
    return `<tr><td>${yearLabel}</td><td>${fmtEUR(f.fee)}</td></tr>`;
  }).join("");
}

// --- Multipliers ---

function renderMultipliers() {
  if (!data) return;
  const isEN = getLang() === "en";
  const body = document.getElementById("multipliers-body")!;
  body.innerHTML = data.multipliers.map((m) => {
    const label = isEN ? m.labelEN : m.label;
    return `<tr>
      <td>${esc(label)}</td>
      <td>${m.courtFeeFactor.toFixed(1)}x</td>
      <td>${m.feeBasis}</td>
      <td>${m.raVGFactor.toFixed(1)}</td>
      <td>${m.raTGFactor.toFixed(1)}</td>
      <td>${m.paVGFactor.toFixed(1)}</td>
      <td>${m.paTGFactor.toFixed(1)}</td>
    </tr>`;
  }).join("");
}

// --- Lookup result display ---

function showLookupResult() {
  const el = document.getElementById("lookup-result")!;
  if (!lookupResult) {
    el.style.display = "none";
    return;
  }

  const isEN = getLang() === "en";
  const sw = lookupResult.streitwert;
  const gkgFee = lookupResult.gkg["2025"] ?? 0;
  const rvgFee = lookupResult.rvg["2025"] ?? 0;

  el.style.display = "block";
  el.innerHTML = `<div class="gebuehren-lookup-cards">
    <div class="gebuehren-lookup-card">
      <span class="gebuehren-lookup-label">${isEN ? "Dispute value" : "Streitwert"}</span>
      <span class="gebuehren-lookup-value">${fmtInt(sw)} EUR</span>
    </div>
    <div class="gebuehren-lookup-card">
      <span class="gebuehren-lookup-label">GKG 1,0</span>
      <span class="gebuehren-lookup-value">${fmtEUR(gkgFee)} EUR</span>
    </div>
    <div class="gebuehren-lookup-card">
      <span class="gebuehren-lookup-label">RVG 1,0</span>
      <span class="gebuehren-lookup-value">${fmtEUR(rvgFee)} EUR</span>
    </div>
  </div>`;
}

// --- Tab switching ---

function initTabs() {
  const container = document.getElementById("gebuehren-tabs")!;
  container.addEventListener("click", (e) => {
    const btn = (e.target as HTMLElement).closest<HTMLButtonElement>(".gebuehren-tab");
    if (!btn) return;
    container.querySelectorAll(".gebuehren-tab").forEach((t) => t.classList.remove("active"));
    btn.classList.add("active");

    const tab = btn.dataset.tab!;
    activeTab = tab;

    // Show/hide panels
    document.querySelectorAll<HTMLElement>(".gebuehren-panel").forEach((p) => {
      p.style.display = "none";
    });
    document.getElementById(`tab-${tab}`)!.style.display = "block";

    // Show multipliers only on GKG/RVG tabs
    const multSection = document.getElementById("multipliers-section")!;
    multSection.style.display = (tab === "gkg" || tab === "rvg") ? "block" : "none";
  });

  // Initial multiplier visibility
  document.getElementById("multipliers-section")!.style.display = "block";
}

// --- Streitwert lookup ---

function parseStreitwert(input: string): number | null {
  // Remove thousands separators (. or ,) and whitespace, then parse
  let cleaned = input.replace(/\s/g, "");
  // Handle German format: 1.000.000,50 → 1000000.50
  if (cleaned.includes(",") && cleaned.includes(".")) {
    cleaned = cleaned.replace(/\./g, "").replace(",", ".");
  } else if (cleaned.includes(",")) {
    // Could be 1000,50 (decimal) or 1,000,000 (thousands)
    const parts = cleaned.split(",");
    if (parts.length === 2 && parts[1].length <= 2) {
      cleaned = cleaned.replace(",", ".");
    } else {
      cleaned = cleaned.replace(/,/g, "");
    }
  } else {
    cleaned = cleaned.replace(/\./g, "");
  }
  const val = parseFloat(cleaned);
  return isNaN(val) || val <= 0 ? null : val;
}

function initLookup() {
  const input = document.getElementById("streitwert-input") as HTMLInputElement;
  const btn = document.getElementById("btn-lookup")!;

  const doIt = () => {
    const val = parseStreitwert(input.value);
    if (val === null) {
      lookupStreitwert = null;
      lookupResult = null;
      document.getElementById("lookup-result")!.style.display = "none";
      renderActivePanel();
      return;
    }
    doLookup(val);
  };

  btn.addEventListener("click", doIt);
  input.addEventListener("keydown", (e) => {
    if (e.key === "Enter") { e.preventDefault(); doIt(); }
  });

  // Clear on empty input
  input.addEventListener("input", () => {
    if (input.value.trim() === "") {
      lookupStreitwert = null;
      lookupResult = null;
      document.getElementById("lookup-result")!.style.display = "none";
      renderAll();
    }
  });
}

// --- Feedback modal ---

function initFeedback() {
  const modal = document.getElementById("feedback-modal")!;
  const form = document.getElementById("feedback-form")!;
  const msg = document.getElementById("feedback-msg")!;

  document.getElementById("btn-feedback")!.addEventListener("click", () => {
    msg.textContent = "";
    msg.className = "form-msg";
    modal.style.display = "flex";
  });

  document.getElementById("modal-close")!.addEventListener("click", () => { modal.style.display = "none"; });
  document.getElementById("modal-cancel")!.addEventListener("click", () => { modal.style.display = "none"; });
  modal.addEventListener("click", (e) => { if (e.target === e.currentTarget) modal.style.display = "none"; });

  form.addEventListener("submit", async (e) => {
    e.preventDefault();
    const submitBtn = form.querySelector(".btn-submit") as HTMLButtonElement;
    const payload = {
      feedback_type: (document.getElementById("feedback-type") as HTMLSelectElement).value,
      schedule: (document.getElementById("feedback-schedule") as HTMLSelectElement).value,
      message: (document.getElementById("feedback-message") as HTMLTextAreaElement).value.trim(),
    };

    if (!payload.message) {
      msg.textContent = t("gebuehren.feedback.error.required");
      msg.className = "form-msg form-msg-error";
      return;
    }

    submitBtn.disabled = true;
    try {
      const resp = await fetch("/api/tools/gebuehrentabellen/feedback", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify(payload),
      });
      if (!resp.ok) {
        msg.textContent = t("gebuehren.feedback.error.generic");
        msg.className = "form-msg form-msg-error";
        return;
      }
      msg.textContent = t("gebuehren.feedback.success");
      msg.className = "form-msg form-msg-success";
      setTimeout(() => { modal.style.display = "none"; }, 1500);
    } catch {
      msg.textContent = t("gebuehren.feedback.error.generic");
      msg.className = "form-msg form-msg-error";
    } finally {
      submitBtn.disabled = false;
    }
  });
}

// --- Init ---

document.addEventListener("DOMContentLoaded", () => {
  initI18n();
  initSidebar();
  initTabs();
  initLookup();
  initFeedback();
  onLangChange(() => {
    renderAll();
    showLookupResult();
  });
  loadData();
});
