(() => {
  const PAGE_SIZE = 10;

  const ICONS = {
    path: `<svg class="pathsMirIcon" width="22" height="22" viewBox="0 0 22 22" aria-hidden="true"><circle cx="5" cy="11" r="2.5" fill="currentColor"/><circle cx="17" cy="11" r="2.5" fill="currentColor"/><path d="M7.5 11h7" stroke="currentColor" stroke-width="1.5" stroke-dasharray="2 2" stroke-linecap="round"/></svg>`,
    view: `<svg width="14" height="14" viewBox="0 0 14 14" aria-hidden="true"><path d="M1 7s2.5-4 6-4 6 4 6 4-2.5 4-6 4-6-4-6-4z" fill="none" stroke="currentColor" stroke-width="1.2"/><circle cx="7" cy="7" r="1.8" fill="none" stroke="currentColor" stroke-width="1.2"/></svg>`,
    delete: `<svg width="14" height="14" viewBox="0 0 14 14" aria-hidden="true"><path d="M4 4l6 6M10 4l-6 6" stroke="currentColor" stroke-width="1.6" stroke-linecap="round"/></svg>`,
  };

  const el = (id) => document.getElementById(id);
  const t = (key, vars) => window.I18n?.t(key, vars) ?? key;

  const listEl = el("pathList");
  const emptyEl = el("pathListEmpty");
  const tableEl = el("pathsTable");
  const filterInputEl = el("pathsFilterInput");
  const filterCountEl = el("pathsFilterCount");
  const pageLabelEl = el("pathsPageLabel");
  const deleteConfirmDialogEl = el("pathDeleteConfirmDialog");
  const deleteConfirmTextEl = el("pathDeleteConfirmText");

  const store = {
    paths: [],
    maps: [],
    sites: [],
    pendingDeleteId: null,
    filter: "",
    page: 1,
  };

  function canWrite() {
    if (!window.AuthApp?.canWrite) return true;
    return window.AuthApp.canWrite("maps");
  }

  function escapeHtml(str) {
    return String(str)
      .replace(/&/g, "&amp;")
      .replace(/</g, "&lt;")
      .replace(/>/g, "&gt;")
      .replace(/"/g, "&quot;");
  }

  async function apiJson(url, opts = {}) {
    const res = await fetch(url, { credentials: "include", ...opts });
    const text = await res.text();
    let data = null;
    try {
      data = text ? JSON.parse(text) : null;
    } catch {
      data = null;
    }
    if (!res.ok) throw new Error((data && data.error) || text || res.statusText);
    return data;
  }

  async function refreshAll() {
    const [sitesData, mapsData, pathsData] = await Promise.all([
      apiJson("/api/sites"),
      apiJson("/api/maps"),
      apiJson("/api/paths"),
    ]);
    store.sites = Array.isArray(sitesData.sites) ? sitesData.sites : [];
    store.maps = Array.isArray(mapsData.maps) ? mapsData.maps : [];
    store.paths = Array.isArray(pathsData.paths) ? pathsData.paths : [];
    return store.paths;
  }

  function mapName(id) {
    return store.maps.find((m) => m.id === id)?.name || id || "—";
  }

  function positionLabel(mapId, positionId) {
    const map = store.maps.find((m) => m.id === mapId);
    const zones = Array.isArray(map?.zones) ? map.zones : [];
    const hit = zones.find((z) => z && z.type === "position" && z.id === positionId);
    const pname = hit?.name || positionId || "—";
    return `${mapName(mapId)} / ${pname}`;
  }

  function filteredPaths() {
    const q = store.filter.trim().toLowerCase();
    let items = [...store.paths];
    if (q) {
      items = items.filter((p) => {
        const from = positionLabel(p.map_id, p.from_position_id).toLowerCase();
        const to = positionLabel(p.map_id, p.to_position_id).toLowerCase();
        const map = mapName(p.map_id).toLowerCase();
        return from.includes(q) || to.includes(q) || map.includes(q);
      });
    }
    return items.sort((a, b) => {
      const ma = mapName(a.map_id).localeCompare(mapName(b.map_id));
      if (ma !== 0) return ma;
      return positionLabel(a.map_id, a.from_position_id).localeCompare(
        positionLabel(b.map_id, b.from_position_id),
      );
    });
  }

  function pageCount(total) {
    return Math.max(1, Math.ceil(total / PAGE_SIZE));
  }

  function renderList() {
    if (!listEl) return;
    const items = filteredPaths();
    const total = items.length;
    const pages = pageCount(total);
    if (store.page > pages) store.page = pages;
    const start = (store.page - 1) * PAGE_SIZE;
    const pageItems = items.slice(start, start + PAGE_SIZE);

    if (filterCountEl) filterCountEl.textContent = t("paths.itemsFound", { n: total });
    if (pageLabelEl) pageLabelEl.textContent = t("paths.pageOf", { page: store.page, total: pages });

    listEl.innerHTML = "";
    if (tableEl) tableEl.hidden = total === 0;
    if (emptyEl) {
      emptyEl.hidden = total > 0;
      emptyEl.textContent = store.filter ? t("paths.emptyFilter") : t("paths.empty");
    }

    pageItems.forEach((path) => {
      const tr = document.createElement("tr");
      tr.className = "pathsMirRow";
      tr.innerHTML = `
        <td class="pathsMirTdIcon">${ICONS.path}</td>
        <td>${escapeHtml(positionLabel(path.map_id, path.from_position_id))}</td>
        <td>${escapeHtml(positionLabel(path.map_id, path.to_position_id))}</td>
        <td>${escapeHtml(mapName(path.map_id))}</td>
        <td class="mapsMirTdFunctions">
          <button type="button" class="mapsMirIconBtn" data-view="${escapeHtml(path.id)}" title="${escapeHtml(t("paths.view"))}">${ICONS.view}</button>
          ${canWrite() ? `<button type="button" class="mapsMirIconBtn mapsMirIconBtn--danger" data-delete="${escapeHtml(path.id)}" title="${escapeHtml(t("common.delete"))}">${ICONS.delete}</button>` : ""}
        </td>`;
      listEl.appendChild(tr);
    });

    document.body.classList.toggle("auth-readonly-paths", !canWrite());
  }

  async function viewPath(id) {
    const path = store.paths.find((p) => p.id === id);
    if (!path) return;
    let full = path;
    try {
      full = await apiJson(`/api/paths/${encodeURIComponent(id)}`);
    } catch {
      /* use list row */
    }
    if (window.MapsApp?.openEditorWithPath) {
      window.NavApp?.selectSection?.("maps", "maps");
      window.MapsApp.openEditorWithPath(full);
    } else {
      alert(t("paths.viewUnavailable"));
    }
  }

  function openDeleteConfirm(id) {
    const path = store.paths.find((p) => p.id === id);
    if (!path) return;
    store.pendingDeleteId = id;
    if (deleteConfirmTextEl) {
      deleteConfirmTextEl.textContent = t("paths.deleteConfirmText", {
        from: positionLabel(path.map_id, path.from_position_id),
        to: positionLabel(path.map_id, path.to_position_id),
      });
    }
    deleteConfirmDialogEl?.showModal();
  }

  async function confirmDelete() {
    const id = store.pendingDeleteId;
    if (!id) return;
    try {
      await apiJson(`/api/paths/${encodeURIComponent(id)}`, { method: "DELETE" });
      store.pendingDeleteId = null;
      deleteConfirmDialogEl?.close();
      await refreshAll();
      renderList();
    } catch (e) {
      alert(e.message);
    }
  }

  function bindEvents() {
    listEl?.addEventListener("click", (evt) => {
      const viewBtn = evt.target.closest("[data-view]");
      const deleteBtn = evt.target.closest("[data-delete]");
      if (viewBtn?.dataset.view) void viewPath(viewBtn.dataset.view);
      else if (deleteBtn?.dataset.delete && canWrite()) openDeleteConfirm(deleteBtn.dataset.delete);
    });

    filterInputEl?.addEventListener("input", () => {
      store.filter = filterInputEl.value;
      store.page = 1;
      renderList();
    });
    el("pathsClearFiltersBtn")?.addEventListener("click", () => {
      store.filter = "";
      store.page = 1;
      if (filterInputEl) filterInputEl.value = "";
      renderList();
    });
    el("pathsPageFirst")?.addEventListener("click", () => {
      store.page = 1;
      renderList();
    });
    el("pathsPagePrev")?.addEventListener("click", () => {
      store.page = Math.max(1, store.page - 1);
      renderList();
    });
    el("pathsPageNext")?.addEventListener("click", () => {
      store.page += 1;
      renderList();
    });
    el("pathsPageLast")?.addEventListener("click", () => {
      store.page = pageCount(filteredPaths().length);
      renderList();
    });
    el("pathsHelpBtn")?.addEventListener("click", () => alert(t("paths.helpBody")));

    deleteConfirmDialogEl?.addEventListener("cancel", (evt) => {
      evt.preventDefault();
      store.pendingDeleteId = null;
      deleteConfirmDialogEl?.close();
    });
    el("pathDeleteCancelBtn")?.addEventListener("click", () => {
      store.pendingDeleteId = null;
      deleteConfirmDialogEl?.close();
    });
    el("pathDeleteYesBtn")?.addEventListener("click", () => confirmDelete().catch((e) => alert(e.message)));

    window.addEventListener("lm:locale-change", () => renderList());
  }

  async function onPageShow() {
    if (!window.AuthApp?.canAccessPage?.("paths")) return;
    await refreshAll();
    renderList();
  }

  function onPageHide() {}

  function init() {
    bindEvents();
  }

  window.PathsApp = { init, onPageShow, onPageHide, refresh: refreshAll };

  function boot() {
    init();
  }

  if (window.AuthApp?.isReady()) boot();
  else window.addEventListener("lm:auth-ready", boot, { once: true });
})();
