/**
 * Модалка выбора компонента-замены (похожие + поиск), как в плане на день.
 */
(function (global) {
  function escapeHtml(value) {
    return String(value ?? "")
      .replace(/&/g, "&amp;")
      .replace(/</g, "&lt;")
      .replace(/>/g, "&gt;")
      .replace(/"/g, "&quot;");
  }

  function formatKg(value) {
    const n = Number(value);
    if (!Number.isFinite(n)) return "—";
    const rounded = Math.round(n * 100) / 100;
    return String(rounded).replace(/\.?0+$/, "");
  }

  function renderComponentPickList(items, emptyText) {
    if (!items.length) {
      return `<p class="zt-k-hub-plan-replace__empty">${escapeHtml(emptyText)}</p>`;
    }
    return items
      .map(
        (item) =>
          `<button type="button" class="zt-k-hub-plan-replace__pick" data-pick-component-id="${escapeHtml(item.id)}" ` +
          `data-pick-component-name="${escapeHtml(item.name)}">` +
          `<span class="zt-k-hub-plan-replace__pick-name">${escapeHtml(item.name)}</span>` +
          `<span class="zt-k-hub-plan-replace__pick-meta">` +
          `${escapeHtml(item.type || "—")} · СВ ${formatKg(item.dryMatter)}%</span></button>`
      )
      .join("");
  }

  async function fetchComponentAlternatives(componentId, query) {
    const params = new URLSearchParams({
      component_id: componentId,
      q: query || "",
      limit: "100",
    });
    const resp = await fetch(`/api/daily-plan/component-alternatives?${params.toString()}`, {
      headers: { Accept: "application/json" },
    });
    if (!resp.ok) {
      const err = await resp.json().catch(() => ({}));
      throw new Error(err.message || "Не удалось загрузить компоненты");
    }
    return resp.json();
  }

  function dismissOverlays(host, keepSelectors) {
    host.querySelectorAll(".zt-k-hub-plan-overlay").forEach((el) => {
      if (keepSelectors.some((sel) => el.matches(sel))) return;
      el.remove();
    });
  }

  /**
   * @param {object} options
   * @param {string} options.componentId
   * @param {string} options.label
   * @param {HTMLElement} [options.overlayHost]
   * @param {string[]} [options.keepOverlays] — селекторы overlay, которые не закрывать
   * @param {string} [options.subtitle]
   * @param {(replacementComponentId: string, replacementName: string) => void|Promise<void>} options.onPick
   * @param {(message: string) => void} [options.onError]
   */
  async function openReplaceComponentModal(options) {
    const {
      componentId,
      label,
      overlayHost = document.body,
      keepOverlays = [],
      subtitle = "",
      onPick,
      onError = () => {},
    } = options || {};
    if (!componentId || !onPick) return;

    const overlay = document.createElement("div");
    overlay.className = "zt-k-hub-plan-overlay zt-k-hub-plan-replace";
    const subtitleHtml = subtitle
      ? `<p class="zt-k-hub-plan-replace__lead">${escapeHtml(subtitle)}</p>`
      : "";
    overlay.innerHTML =
      '<div class="zt-k-hub-plan-subdialog zt-k-hub-plan-replace__dialog" role="dialog" aria-modal="true">' +
      `<h3 class="zt-k-hub-plan-subdialog__title zt-k-hub-plan-replace__title">Заменить «${escapeHtml(label)}»</h3>` +
      subtitleHtml +
      '<label class="zt-k-hub-plan-replace__search-label">Поиск по всем компонентам</label>' +
      '<input type="search" class="form-control zt-k-hub-plan-replace__search" data-replace-search placeholder="Начните вводить название…" autocomplete="off">' +
      '<div class="zt-k-hub-plan-replace__section">' +
      '<p class="zt-k-hub-plan-replace__section-title">Похожие по параметрам</p>' +
      '<div data-replace-similar class="zt-k-hub-plan-replace__list"><div class="zt-k-hub-plan-replace__empty">Загрузка…</div></div></div>' +
      '<div class="zt-k-hub-plan-replace__section">' +
      '<p class="zt-k-hub-plan-replace__section-title">Все компоненты</p>' +
      '<div data-replace-results class="zt-k-hub-plan-replace__list"><div class="zt-k-hub-plan-replace__empty">Загрузка…</div></div></div>' +
      '<div class="zt-k-hub-plan-subdialog__actions zt-k-hub-plan-replace__actions">' +
      '<button type="button" class="btn btn-secondary" data-replace-cancel>Отмена</button></div></div>';

    dismissOverlays(overlayHost, keepOverlays);
    overlay.setAttribute("data-daily-plan-overlay", "1");
    overlayHost.appendChild(overlay);

    const similarEl = overlay.querySelector("[data-replace-similar]");
    const resultsEl = overlay.querySelector("[data-replace-results]");
    const searchEl = overlay.querySelector("[data-replace-search]");
    let catalog = null;

    const close = () => {
      if (overlay.isConnected) overlay.remove();
    };

    function filterCatalog(query) {
      const q = query.trim().toLowerCase();
      if (!q) {
        return {
          similar: catalog?.similar || [],
          items: catalog?.results || [],
          q: "",
        };
      }
      const items = (catalog?.results || []).filter((item) =>
        String(item.name || "").toLowerCase().includes(q)
      );
      const similar = items.filter((item) => item.similar);
      return { similar, items, q };
    }

    function paintLists(query = "") {
      if (!overlay.isConnected) return;
      const { similar, items, q } = filterCatalog(query);
      if (similarEl) {
        similarEl.innerHTML = renderComponentPickList(
          similar,
          q ? "Нет похожих по запросу" : "Нет похожих компонентов"
        );
      }
      if (resultsEl) {
        resultsEl.innerHTML = renderComponentPickList(
          items,
          q ? "Ничего не найдено" : "Нет доступных компонентов"
        );
      }
    }

    async function loadCatalog() {
      try {
        catalog = await fetchComponentAlternatives(componentId, "");
        paintLists(searchEl?.value.trim() || "");
      } catch (err) {
        if (!overlay.isConnected) return;
        onError(err.message || "Не удалось загрузить компоненты");
      }
    }

    overlay.querySelector("[data-replace-cancel]")?.addEventListener("click", close);
    overlay.addEventListener("click", (event) => {
      if (event.target === overlay) close();
    });
    searchEl?.addEventListener("input", () => paintLists(searchEl.value.trim()));
    overlay.addEventListener("click", async (event) => {
      const pick = event.target.closest("[data-pick-component-id]");
      if (!pick) return;
      event.preventDefault();
      const replacementComponentId = pick.dataset.pickComponentId;
      const replacementName = pick.dataset.pickComponentName || "Компонент";
      if (!replacementComponentId) return;
      close();
      try {
        await onPick(replacementComponentId, replacementName);
      } catch (err) {
        onError(err.message || "Не удалось заменить компонент");
      }
    });

    await loadCatalog();
    searchEl?.focus();
  }

  global.WespDailyPlanReplaceModal = {
    open: openReplaceComponentModal,
    fetchComponentAlternatives,
  };
})(window);
