(function (global) {
  "use strict";

  let observer = null;

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

  function planDate() {
    return (
      global.WespDailyPlanPanel?.getSelectedPlanDate?.() ||
      global.WespDailyPlanSkipDuration?.todayIso?.() ||
      new Date().toISOString().slice(0, 10)
    );
  }

  function getRecipeId() {
    return (
      document.getElementById("recipeEdit")?.dataset?.recipeId ||
      document.querySelector(".list-item.active[data-recipe-id]")?.dataset?.recipeId ||
      null
    );
  }

  function notifySuccess(message) {
    global.WespZootechNotify?.createAdapter?.()?.success?.(message);
  }

  function notifyError(message, fallback) {
    global.WespZootechNotify?.createAdapter?.()?.error?.(message, { fallback: fallback || message });
  }

  async function reloadEditor() {
    const recipeId = getRecipeId();
    if (!recipeId) return;
    if (typeof global.reloadRecipeEditor === "function") {
      await global.reloadRecipeEditor(recipeId);
    } else if (typeof global.loadRecipeDetailsWithPlanOverlay === "function") {
      await global.loadRecipeDetailsWithPlanOverlay();
    } else if (typeof global.loadRecipeDetails === "function") {
      await global.loadRecipeDetails(recipeId);
    }
  }

  function planBtnHtml(action, title, icon, attrs = "") {
    return (
      `<button type="button" class="btn btn-outline-secondary btn-sm recipe-plan-action-btn" ` +
      `data-action="${action}" title="${escapeHtml(title)}" ${attrs}>` +
      `<i class="fas ${icon}"></i></button>`
    );
  }

  function decorateRow(row) {
    const actions = row.querySelector(".recipe-table-row-actions");
    if (!actions || actions.querySelector(".recipe-plan-actions")) return;

    const ingredientId = row.dataset.id;
    if (!ingredientId) return;

    const skipped = row.classList.contains("ingredient-row--skipped");
    const replaced = row.classList.contains("ingredient-row--replaced");
    const select = row.querySelector(".ingredient-select");
    const componentId = select?.value || "";
    const label = select?.selectedOptions?.[0]?.textContent?.trim() || "Компонент";
    const recipeId = getRecipeId();
    if (!recipeId) return;

    const wrap = document.createElement("div");
    wrap.className = "btn-group recipe-plan-actions me-1";
    wrap.setAttribute("role", "group");

    if (skipped) {
      wrap.innerHTML = planBtnHtml(
        "recipe-plan-unskip-ingredient",
        "Вернуть в план",
        "fa-undo",
        `data-recipe-id="${escapeHtml(recipeId)}" data-ingredient-id="${escapeHtml(ingredientId)}"`
      );
    } else if (replaced) {
      wrap.innerHTML = planBtnHtml(
        "recipe-plan-undo-replace-ingredient",
        "Отменить замену",
        "fa-undo",
        `data-recipe-id="${escapeHtml(recipeId)}" data-ingredient-id="${escapeHtml(ingredientId)}"`
      );
    } else {
      wrap.innerHTML =
        planBtnHtml(
          "recipe-plan-skip-ingredient",
          "Убрать из плана",
          "fa-ban",
          `data-recipe-id="${escapeHtml(recipeId)}" data-ingredient-id="${escapeHtml(ingredientId)}" data-label="${escapeHtml(label)}"`
        ) +
        (componentId
          ? planBtnHtml(
              "recipe-plan-replace-ingredient",
              "Заменить в плане",
              "fa-exchange-alt",
              `data-recipe-id="${escapeHtml(recipeId)}" data-ingredient-id="${escapeHtml(ingredientId)}" ` +
                `data-component-id="${escapeHtml(componentId)}" data-label="${escapeHtml(label)}"`
            )
          : "");
    }

    const deleteBtn = actions.querySelector('[data-action="remove-ingredient"]');
    if (deleteBtn) actions.insertBefore(wrap, deleteBtn);
    else actions.appendChild(wrap);
  }

  function decorateRows() {
    document.querySelectorAll("#ingredientsTableBody .ingredient-row").forEach(decorateRow);
  }

  function ensureStyles() {
    if (document.getElementById("wesp-lab-plan-overlay-styles")) return;
    const style = document.createElement("style");
    style.id = "wesp-lab-plan-overlay-styles";
    style.textContent =
      ".recipe-plan-action-btn{padding:2px 6px;}" +
      ".recipe-plan-actions .btn+.btn{margin-left:2px;}";
    document.head.appendChild(style);
  }

  async function skipIngredient(recipeId, ingredientId, label) {
    const skip = global.WespDailyPlanSkipDuration;
    if (!skip?.skipDurationBody) return;
    const body = await skip.skipDurationBody(planDate(), { recipeId, ingredientId }, "На какой срок убрать компонент?");
    if (!body) return;
    const resp = await fetch("/api/daily-plan/skips/ingredients", {
      method: "POST",
      headers: { "Content-Type": "application/json", Accept: "application/json" },
      body: JSON.stringify(body),
    });
    if (!resp.ok) {
      const err = await resp.json().catch(() => ({}));
      throw new Error(err.message || "Не удалось убрать компонент");
    }
    await reloadEditor();
    notifySuccess(`«${label}» убран из плана`);
  }

  async function unskipIngredient(recipeId, ingredientId) {
    const params = new URLSearchParams({ recipe_id: recipeId, ingredient_id: ingredientId, date: planDate() });
    const resp = await fetch(`/api/daily-plan/skips/ingredients?${params}`, {
      method: "DELETE",
      headers: { Accept: "application/json" },
    });
    if (!resp.ok) {
      const err = await resp.json().catch(() => ({}));
      throw new Error(err.message || "Не удалось вернуть компонент");
    }
    await reloadEditor();
    notifySuccess("Компонент снова в плане");
  }

  async function openReplace(recipeId, ingredientId, componentId, label) {
    const replaceModal = global.WespDailyPlanReplaceModal;
    if (!replaceModal?.open) {
      notifyError("Модалка замены недоступна");
      return;
    }
    await replaceModal.open({
      currentName: label,
      onPick: async (replacementComponentId, replacementName) => {
        const skip = global.WespDailyPlanSkipDuration;
        const body = await skip?.skipDurationBody?.(
          planDate(),
          { recipeId, ingredientId, replacementComponentId },
          "На какой срок заменить компонент?"
        );
        if (!body) return;
        const resp = await fetch("/api/daily-plan/replacements/ingredients", {
          method: "POST",
          headers: { "Content-Type": "application/json", Accept: "application/json" },
          body: JSON.stringify(body),
        });
        if (!resp.ok) {
          const err = await resp.json().catch(() => ({}));
          throw new Error(err.message || "Не удалось заменить компонент");
        }
        await reloadEditor();
        notifySuccess(`Компонент заменён на «${replacementName}»`);
      },
    });
  }

  async function undoReplace(recipeId, ingredientId) {
    const params = new URLSearchParams({ recipe_id: recipeId, ingredient_id: ingredientId, date: planDate() });
    const resp = await fetch(`/api/daily-plan/replacements/ingredients?${params}`, {
      method: "DELETE",
      headers: { Accept: "application/json" },
    });
    if (!resp.ok) {
      const err = await resp.json().catch(() => ({}));
      throw new Error(err.message || "Не удалось отменить замену");
    }
    await reloadEditor();
    notifySuccess("Замена отменена");
  }

  document.addEventListener("click", async (ev) => {
    const btn = ev.target.closest("[data-action]");
    if (!btn) return;
    const action = btn.dataset.action;
    if (!action?.startsWith("recipe-plan-")) return;
    if (!document.getElementById("recipeEdit")?.contains(btn)) return;
    ev.preventDefault();

    const recipeId = btn.dataset.recipeId;
    const ingredientId = btn.dataset.ingredientId;
    try {
      if (action === "recipe-plan-skip-ingredient") {
        await skipIngredient(recipeId, ingredientId, btn.dataset.label || "Компонент");
      } else if (action === "recipe-plan-unskip-ingredient") {
        await unskipIngredient(recipeId, ingredientId);
      } else if (action === "recipe-plan-replace-ingredient") {
        await openReplace(recipeId, ingredientId, btn.dataset.componentId, btn.dataset.label || "Компонент");
      } else if (action === "recipe-plan-undo-replace-ingredient") {
        await undoReplace(recipeId, ingredientId);
      }
    } catch (e) {
      notifyError(e.message, "Ошибка плана");
    }
  });

  function watchIngredients() {
    const tbody = document.getElementById("ingredientsTableBody");
    if (!tbody || observer) return;
    observer = new MutationObserver(() => decorateRows());
    observer.observe(tbody, { childList: true, subtree: true });
  }

  global.WespLabRecipesPlanOverlay = {
    init() {
      ensureStyles();
      watchIngredients();
      decorateRows();
    },
    decorateRows,
  };

  if (document.readyState === "loading") {
    document.addEventListener("DOMContentLoaded", () => global.WespLabRecipesPlanOverlay.init());
  } else {
    global.WespLabRecipesPlanOverlay.init();
  }
})(window);
