(() => {
  const COIL_MIN = 1001;
  const COIL_MAX = 2000;

  const el = (id) => document.getElementById(id);
  const t = (key, vars) => window.I18n?.t(key, vars) ?? key;
  const triggerListEl = el("integrationTriggerList");
  const triggerEmptyEl = el("integrationTriggerEmpty");
  const coilGridEl = el("integrationCoilGrid");
  const scheduleListEl = el("integrationScheduleList");
  const scheduleEmptyEl = el("integrationScheduleEmpty");
  const addTriggerDialogEl = el("integrationAddTriggerDialog");
  const addScheduleDialogEl = el("integrationAddScheduleDialog");
  const apiBaseUrlEl = el("integrationApiBaseUrl");

  const store = {
    triggers: [],
    schedules: [],
    robots: [],
    coils: {},
    missions: [],
    pollTimer: null,
  };

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

  function missionName(id) {
    const m = store.missions.find((x) => x.id === id);
    return m ? m.name : id;
  }

  function robotLabel(id) {
    const r = store.robots.find((x) => x.id === id);
    return r ? r.name || r.id : id || "default";
  }

  async function apiJson(url, opts = {}) {
    if (window.AuthApp && !window.AuthApp.isReady()) {
      throw new Error("not authenticated");
    }
    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) {
      const msg = (data && data.error) || text || res.statusText;
      throw new Error(msg);
    }
    return data;
  }

  async function refreshMissions() {
    try {
      const data = await apiJson("/api/missions");
      store.missions = Array.isArray(data.missions) ? data.missions : [];
    } catch {
      store.missions = window.MissionsApp?.getMissions?.() || [];
    }
  }

  async function refreshRobots() {
    try {
      const data = await apiJson("/api/fleet/robots");
      store.robots = Array.isArray(data) ? data : [];
    } catch {
      store.robots = [{ id: "default", name: t("integrations.defaultRobot") }];
    }
  }

  async function refreshTriggers() {
    store.triggers = await apiJson("/api/triggers");
    if (!Array.isArray(store.triggers)) store.triggers = [];
  }

  async function refreshSchedules() {
    store.schedules = await apiJson("/api/fleet/schedules");
    if (!Array.isArray(store.schedules)) store.schedules = [];
  }

  async function refreshCoils() {
    store.coils = (await apiJson("/api/modbus/coils")) || {};
  }

  function fillMissionSelect(selectEl, selected) {
    if (!selectEl) return;
    selectEl.innerHTML = "";
    if (!store.missions.length) {
      const opt = document.createElement("option");
      opt.value = "";
      opt.textContent = t("integrations.noMissions");
      selectEl.appendChild(opt);
      return;
    }
    store.missions.forEach((m) => {
      const opt = document.createElement("option");
      opt.value = m.id;
      opt.textContent = m.name;
      if (m.id === selected) opt.selected = true;
      selectEl.appendChild(opt);
    });
  }

  function fillRobotSelect(selectEl, selected) {
    if (!selectEl) return;
    selectEl.innerHTML = "";
    store.robots.forEach((r) => {
      const opt = document.createElement("option");
      opt.value = r.id;
      opt.textContent = r.name || r.id;
      if (r.id === selected) opt.selected = true;
      selectEl.appendChild(opt);
    });
    if (!store.robots.length) {
      const opt = document.createElement("option");
      opt.value = "default";
      opt.textContent = t("integrations.defaultRobot");
      opt.selected = selected === "default";
      selectEl.appendChild(opt);
    }
  }

  function renderTriggers() {
    if (!triggerListEl) return;
    triggerListEl.innerHTML = "";
    if (triggerEmptyEl) triggerEmptyEl.hidden = store.triggers.length > 0;

    store.triggers.forEach((trigger) => {
      const row = document.createElement("div");
      row.className = "missionListItem integrationRow";
      const coil = trigger.coil_id;
      const on = store.coils[String(coil)] === true;
      row.innerHTML = `
        <div>
          <div class="missionListItemTitle">${escapeHtml(trigger.name)}</div>
          <div class="missionListItemMeta">
            Coil <span class="mono">${coil}</span>
            → ${escapeHtml(missionName(trigger.mission_id))}
            · ${trigger.enabled === false ? t("common.disabled") : t("common.enabled")}
            · ${t("integrations.coilState", { state: on ? "ON" : "OFF" })}
          </div>
        </div>
        <div class="missionListItemActions">
          <button type="button" class="btn subtle" data-fire-coil="${coil}">${t("integrations.fireTrigger")}</button>
          <button type="button" class="btn subtle danger" data-delete-trigger="${escapeHtml(trigger.id)}">${t("common.delete")}</button>
        </div>`;
      triggerListEl.appendChild(row);
    });
  }

  function renderCoilGrid() {
    if (!coilGridEl) return;
    const assigned = new Map(store.triggers.map((t) => [t.coil_id, t]));
    const chips = [];
    assigned.forEach((trigger, coilId) => {
      const on = store.coils[String(coilId)] === true;
      chips.push(
        `<button type="button" class="integrationCoilChip${on ? " on" : ""}" data-fire-coil="${coilId}" title="${escapeHtml(trigger.name)}">
          ${coilId}
        </button>`
      );
    });
    coilGridEl.innerHTML =
      chips.length > 0
        ? chips.join("")
        : `<span class="mutedNote">${t("integrations.coilsEmpty")}</span>`;
  }

  function formatScheduleTime(s) {
    if (!s.start_at) return s.start_mode === "scheduled" ? "—" : t("integrations.dialog.schedule.asap");
    try {
      return new Date(s.start_at).toLocaleString("vi-VN");
    } catch {
      return String(s.start_at);
    }
  }

  function renderSchedules() {
    if (!scheduleListEl) return;
    scheduleListEl.innerHTML = "";
    if (scheduleEmptyEl) scheduleEmptyEl.hidden = store.schedules.length > 0;

    store.schedules.forEach((s) => {
      const row = document.createElement("div");
      row.className = "missionListItem integrationRow";
      row.innerHTML = `
        <div>
          <div class="missionListItemTitle">${escapeHtml(s.name)}</div>
          <div class="missionListItemMeta">
            ${escapeHtml(missionName(s.mission_id))}
            · robot: ${escapeHtml(robotLabel(s.robot_id))}
            · ưu tiên ${s.priority ?? 0}
            · ${s.start_mode === "scheduled" ? "Lên lịch" : "ASAP"}
            · ${formatScheduleTime(s)}
            · ${s.enabled === false ? "Tắt" : "Bật"}
          </div>
        </div>
        <div class="missionListItemActions">
          <button type="button" class="btn subtle" data-run-schedule="${escapeHtml(s.id)}">${t("integrations.schedule.runNow")}</button>
          <button type="button" class="btn subtle danger" data-delete-schedule="${escapeHtml(s.id)}">Xóa</button>
        </div>`;
      scheduleListEl.appendChild(row);
    });
  }

  function updateApiBaseUrl() {
    const origin = window.location.origin;
    if (apiBaseUrlEl) apiBaseUrlEl.textContent = `${origin}/api/v2.0.0`;
    document.querySelectorAll(".integrationCurlHost").forEach((node) => {
      node.textContent = origin;
    });
  }

  async function refreshAll() {
    await refreshMissions();
    await Promise.all([refreshRobots(), refreshTriggers(), refreshSchedules(), refreshCoils()]);
    renderTriggers();
    renderCoilGrid();
    renderSchedules();
    updateApiBaseUrl();
  }

  async function openAddTriggerDialog() {
    await refreshMissions();
    fillMissionSelect(el("integrationTriggerMission"));
    const coilInput = el("integrationTriggerCoil");
    if (coilInput) coilInput.value = "1001";
    el("integrationTriggerName").value = "";
    addTriggerDialogEl?.showModal();
  }

  async function submitAddTrigger(evt) {
    evt.preventDefault();
    const name = el("integrationTriggerName").value.trim();
    const coil_id = Number(el("integrationTriggerCoil").value);
    const mission_id = el("integrationTriggerMission").value;
    if (!name || !mission_id) return;
    if (coil_id < COIL_MIN || coil_id > COIL_MAX) {
      alert(`Coil phải từ ${COIL_MIN} đến ${COIL_MAX}`);
      return;
    }
    try {
      await apiJson("/api/triggers", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ name, coil_id, mission_id, enabled: true }),
      });
      addTriggerDialogEl?.close();
      await refreshAll();
    } catch (err) {
      alert(err.message || "Không thêm được trigger");
    }
  }

  async function openAddScheduleDialog() {
    await Promise.all([refreshMissions(), refreshRobots()]);
    fillMissionSelect(el("integrationScheduleMission"));
    fillRobotSelect(el("integrationScheduleRobot"), "default");
    el("integrationScheduleName").value = "";
    el("integrationSchedulePriority").value = "0";
    el("integrationScheduleMode").value = "asap";
    el("integrationScheduleStartAt").value = "";
    toggleScheduleStartAt();
    addScheduleDialogEl?.showModal();
  }

  function toggleScheduleStartAt() {
    const mode = el("integrationScheduleMode")?.value || "asap";
    const row = el("integrationScheduleStartAtRow");
    if (row) row.hidden = mode !== "scheduled";
  }

  async function submitAddSchedule(evt) {
    evt.preventDefault();
    const name = el("integrationScheduleName").value.trim();
    const mission_id = el("integrationScheduleMission").value;
    const robot_id = el("integrationScheduleRobot").value || "default";
    const priority = Number(el("integrationSchedulePriority").value) || 0;
    const start_mode = el("integrationScheduleMode").value || "asap";
    const startRaw = el("integrationScheduleStartAt").value;
    if (!name || !mission_id) return;
    const payload = { name, mission_id, robot_id, priority, start_mode, enabled: true };
    if (start_mode === "scheduled" && startRaw) {
      payload.start_at = new Date(startRaw).toISOString();
    }
    try {
      await apiJson("/api/fleet/schedules", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify(payload),
      });
      addScheduleDialogEl?.close();
      await refreshAll();
    } catch (err) {
      alert(err.message || "Không thêm được lịch");
    }
  }

  async function fireCoil(coilId) {
    try {
      await apiJson(`/api/modbus/coils/${coilId}/trigger`, { method: "POST" });
      await refreshCoils();
      renderTriggers();
      renderCoilGrid();
    } catch (err) {
      alert(err.message || "Không kích hoạt được coil");
    }
  }

  async function deleteTrigger(id) {
    if (!confirm(t("integrations.confirm.deleteTrigger"))) return;
    try {
      await apiJson(`/api/triggers/${id}`, { method: "DELETE" });
      await refreshAll();
    } catch (err) {
      alert(err.message || "Không xóa được");
    }
  }

  async function deleteSchedule(id) {
    if (!confirm(t("integrations.confirm.deleteSchedule"))) return;
    try {
      await apiJson(`/api/fleet/schedules/${id}`, { method: "DELETE" });
      await refreshAll();
    } catch (err) {
      alert(err.message || "Không xóa được");
    }
  }

  async function runSchedule(id) {
    try {
      await apiJson(`/api/fleet/schedules/${id}/run`, { method: "POST" });
      window.MissionsApp?.refreshQueue?.();
    } catch (err) {
      alert(err.message || "Không chạy được lịch");
    }
  }

  async function testRestEnqueue() {
    const missionId = el("integrationRestMission")?.value;
    if (!missionId) {
      alert("Chọn mission để thử");
      return;
    }
    try {
      const data = await apiJson("/api/v2.0.0/mission_queue", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ mission_id: missionId, priority: 0 }),
      });
      alert(`Đã thêm vào queue — id ${data.id}`);
      window.MissionsApp?.refreshQueue?.();
    } catch (err) {
      alert(err.message || "POST thất bại");
    }
  }

  function bindEvents() {
    el("integrationAddTriggerBtn")?.addEventListener("click", openAddTriggerDialog);
    el("integrationAddScheduleBtn")?.addEventListener("click", openAddScheduleDialog);
    el("integrationRefreshBtn")?.addEventListener("click", () => refreshAll());
    el("integrationAddTriggerForm")?.addEventListener("submit", submitAddTrigger);
    el("integrationAddScheduleForm")?.addEventListener("submit", submitAddSchedule);
    el("integrationScheduleMode")?.addEventListener("change", toggleScheduleStartAt);
    el("integrationRestTestBtn")?.addEventListener("click", testRestEnqueue);

    triggerListEl?.addEventListener("click", (evt) => {
      const coilBtn = evt.target.closest("[data-fire-coil]");
      if (coilBtn) {
        fireCoil(Number(coilBtn.getAttribute("data-fire-coil")));
        return;
      }
      const delBtn = evt.target.closest("[data-delete-trigger]");
      if (delBtn) deleteTrigger(delBtn.getAttribute("data-delete-trigger"));
    });

    coilGridEl?.addEventListener("click", (evt) => {
      const btn = evt.target.closest("[data-fire-coil]");
      if (btn) fireCoil(Number(btn.getAttribute("data-fire-coil")));
    });

    scheduleListEl?.addEventListener("click", (evt) => {
      const runBtn = evt.target.closest("[data-run-schedule]");
      if (runBtn) {
        runSchedule(runBtn.getAttribute("data-run-schedule"));
        return;
      }
      const delBtn = evt.target.closest("[data-delete-schedule]");
      if (delBtn) deleteSchedule(delBtn.getAttribute("data-delete-schedule"));
    });

    document.querySelectorAll("[data-close-dialog]").forEach((btn) => {
      btn.addEventListener("click", () => {
        const id = btn.getAttribute("data-close-dialog");
        el(id)?.close();
      });
    });
  }

  function startPoll() {
    stopPoll();
    store.pollTimer = setInterval(async () => {
      try {
        await refreshCoils();
        renderTriggers();
        renderCoilGrid();
      } catch {
        /* ignore */
      }
    }, 3000);
  }

  function stopPoll() {
    if (store.pollTimer) {
      clearInterval(store.pollTimer);
      store.pollTimer = null;
    }
  }

  async function onPageShow() {
    await refreshAll();
    fillMissionSelect(el("integrationRestMission"));
    startPoll();
  }

  function init() {
    bindEvents();
    updateApiBaseUrl();
  }

  window.IntegrationsApp = {
    init,
    onPageShow,
    onPageHide: stopPoll,
    refreshAll,
  };

  function boot() {
    init();
  }
  window.addEventListener("lm:locale-change", () => {
    renderTriggers();
    renderCoilGrid();
    renderSchedules();
  });

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