(function (global) {
  "use strict";

  /** Показатели для зоотех-расчёта рациона (weighted average). */
  const NUTRIENT_ROWS = [
    {
      label: "Осн. корм",
      unit: "г/кг СВ",
      keys: ["Осн.Корм"],
      hint: "СВ этого сырья, учитываемое как объёмный (основной) корм в норме dm_main. 0 — концентрат/добавка.",
    },
    { label: "Сыр. протеин", unit: "г/кг", keys: ["Сыр. Протеин"] },
    { label: "уСП", unit: "г/кг", keys: ["уСП"] },
    { label: "RNB", unit: "г/кг", keys: ["RNB", "БРА", "    БРА "] },
    { label: "ЧЭЛ — КРС", unit: "МДж/кг", keys: ["ЧЭЛ- КРС", "    ЧЭЛ- КРС"] },
    { label: "ОЭ — КРС", unit: "МДж/кг", keys: ["ОЭ-КРС", "    ОЭ-КРС"] },
    { label: "Сырая клетчатка", unit: "г/кг", keys: ["Сырая клетч", "Сырая клетчатка"] },
    { label: "Структур. клетч.", unit: "г/кг", keys: ["Структур клетч", "Структур. клетч", "Структур. клетчатка"] },
    { label: "Сырой жир", unit: "г/кг", keys: ["Сырой жир"] },
  ];

  /** Лаб. ввод для native derive (см. LAB_FORMULAS.md). СВ — только component.dry_matter (%). */
  const LAB_INPUT_ROWS = [
    { label: "Сырая зола", unit: "г/кг", keys: ["Сырая зола"] },
    {
      label: "ВРХ орг. вещ.",
      unit: "%",
      keys: ["ВРХ Орг Вещ"],
      hint: "Обязательно для грубых и сочных кормов. Без значения подставится дефолт WESP (65% / 72%).",
    },
    {
      label: "уСП в ОР",
      unit: "г/кг",
      keys: ["уСП в ОР", "уСП в ОВ"],
      hint: "Лабораторное уСП: при значении > 1 заменяет расчёт по формуле Lebzien.",
    },
    { label: "КРС протеин", unit: "%", keys: ["КРС Протеин"] },
    { label: "КРС сырой жир", unit: "%", keys: ["КРС Сырой жир"] },
    { label: "КРС сырая клетч.", unit: "%", keys: ["КРС Сырая клетч"] },
    { label: "КРС БЭВ", unit: "%", keys: ["КРС БЭВ"] },
    { label: "НДК", unit: "г/кг", keys: ["НДК", "НДК Общ"] },
    { label: "NFC", unit: "г/кг", keys: ["NFC", "БЕР"] },
  ];

  /** Минералы, аминокислоты и прочий лаб. ввод из AgroStar / импорта. */
  const EXTRA_LAB_ROWS = [
    { label: "КДК (ADF)", unit: "г/кг", keys: ["КДК", "КДК общ"] },
    { label: "Ca", unit: "г/кг", keys: ["Ca"] },
    { label: "P", unit: "г/кг", keys: ["P"] },
    { label: "Mg", unit: "г/кг", keys: ["Mg"] },
    { label: "K", unit: "г/кг", keys: ["K"] },
    { label: "S", unit: "г/кг", keys: ["S"] },
    { label: "Cl", unit: "г/кг", keys: ["CL", "Cl"] },
    { label: "Сахар", unit: "г/кг", keys: ["Сахар"] },
    { label: "Крахмал", unit: "г/кг", keys: ["Крахмал"] },
    { label: "Нераств. протеин", unit: "%", keys: ["%  нераствор протеин"] },
    { label: "Лизин", unit: "г/кг", keys: ["Лизин"] },
    { label: "Метионин", unit: "г/кг", keys: ["Метионин"] },
    { label: "Лейцин", unit: "г/кг", keys: ["Лейцин"] },
    { label: "Изолейцин", unit: "г/кг", keys: ["Изолейцин"] },
    { label: "Валин", unit: "г/кг", keys: ["Валин"] },
  ];

  const ALL_FORM_ROWS = [...NUTRIENT_ROWS, ...LAB_INPUT_ROWS, ...EXTRA_LAB_ROWS];

  const CARD_INFO_COLUMNS = [
    {
      label: "Сухое вещество",
      value(component) {
        const dm = component.dryMatter ?? component.dry_matter;
        return dm == null || dm === "" ? "—" : `${dm}%`;
      },
    },
    {
      label: "№ справочника",
      value(component) {
        const n = component.externalNo ?? component.external_no;
        return n == null || n === "" ? "—" : String(n);
      },
    },
    {
      label: "Цена",
      value(component) {
        const price = component.price;
        return price == null || price === "" ? "—" : `${price} руб/кг`;
      },
    },
    {
      label: "Осн. корм",
      value(_component, nutrients) {
        const val = readNutrientValue(nutrients, ["Осн.Корм"]);
        return val == null ? "—" : `${val} г/кг`;
      },
    },
    {
      label: "Сыр. протеин",
      value(_component, nutrients) {
        const val = readNutrientValue(nutrients, ["Сыр. Протеин"]);
        return val == null ? "—" : `${val} г/кг`;
      },
    },
    {
      label: "ОЭ — КРС",
      value(_component, nutrients) {
        const val = readNutrientValue(nutrients, ["ОЭ-КРС", "    ОЭ-КРС"]);
        return val == null ? "—" : `${val} МДж/кг`;
      },
    },
    {
      label: "СВ (расч.)",
      value(component) {
        const dm = component.dryMatter ?? component.dry_matter;
        if (dm == null || dm === "") return "—";
        const n = Number(dm);
        if (Number.isNaN(n)) return "—";
        return `${(n * 10).toFixed(1)} г/кг`;
      },
    },
    {
      label: "Показателей",
      value(_component, nutrients) {
        return String(Object.keys(nutrients || {}).length);
      },
    },
  ];

  function normalizeKey(s) {
    return String(s || "")
      .replace(/\s+/g, " ")
      .trim()
      .toLowerCase();
  }

  function parseNutrients(raw) {
    if (!raw) return {};
    if (typeof raw === "object") return { ...raw };
    try {
      return JSON.parse(raw) || {};
    } catch (_) {
      return {};
    }
  }

  function readNutrientValue(nutrients, keys) {
    const map = nutrients || {};
    for (const search of keys) {
      const target = normalizeKey(search);
      for (const [k, v] of Object.entries(map)) {
        if (normalizeKey(k) !== target) continue;
        const n = Number(v);
        if (!Number.isNaN(n)) return n;
      }
    }
    return null;
  }

  function canonicalKey(keys) {
    return keys[0];
  }

  function buildNutrientsPayload(root) {
    const payload = {};
    if (!root) return payload;
    root.querySelectorAll("[data-nutrient-key]").forEach((input) => {
      const key = input.getAttribute("data-nutrient-key");
      const val = input.value.trim();
      if (key && val !== "") payload[key] = Number(val);
    });
    return payload;
  }

  function rowFieldsHtml(rows, nutrients) {
    return rows
      .map((row) => {
        const key = canonicalKey(row.keys);
        const val = readNutrientValue(nutrients, row.keys);
        const hint = row.hint ? ` title="${row.hint}"` : "";
        return (
          `<div class="lab-nutrient-field"${hint}>` +
          `<label class="form-label small mb-0 lab-nutrient-field__label">${row.label}` +
          `<span class="text-muted"> (${row.unit})</span></label>` +
          `<input type="number" step="0.01" class="form-control form-control-sm" ` +
          `data-nutrient-key="${key}" value="${val == null ? "" : val}" placeholder="—">` +
          `</div>`
        );
      })
      .join("");
  }

  const _OMD_FEED_TYPES = new Set(["грубые корма", "сочные корма", "объемные корма", "объёмные корма"]);

  function feedGroupNeedsOmd(component) {
    if (!component || !component.type) return false;
    return _OMD_FEED_TYPES.has(normalizeKey(component.type));
  }

  function omdWarningHtml(component, nutrients) {
    if (!feedGroupNeedsOmd(component)) return "";
    if (readNutrientValue(nutrients, ["ВРХ Орг Вещ", "КРС Орг Вещ"]) != null) return "";
    return (
      `<div class="alert alert-warning py-2 px-3 small mb-2" role="status">` +
      `Для грубых и сочных кормов укажите <strong>ВРХ орг. вещ.</strong> — ` +
      `без анализа расчёт энергии и уСП будет ненадёжным.` +
      `</div>`
    );
  }

  function nutrientsFormHtml(nutrients, component) {
    const calcRows = rowFieldsHtml(NUTRIENT_ROWS, nutrients);
    const labRows = rowFieldsHtml(LAB_INPUT_ROWS, nutrients);
    const extraRows = rowFieldsHtml(EXTRA_LAB_ROWS, nutrients);
    const warn = omdWarningHtml(component, nutrients);
    return (
      warn +
      `<div class="lab-nutrients-block" data-lab-nutrients-block>` +
      `<div class="lab-nutrients-block__head">` +
      `<i class="fas fa-flask text-primary me-1"></i>` +
      `<span class="lab-nutrients-block__title">Показатели для расчёта рациона</span>` +
      `</div>` +
      `<div class="lab-nutrients-row lab-nutrients-row--calc">${calcRows}</div>` +
      `</div>` +
      `<div class="lab-nutrients-block lab-nutrients-block--lab-input mt-3" data-lab-nutrients-lab>` +
      `<div class="lab-nutrients-block__head">` +
      `<i class="fas fa-vial text-secondary me-1"></i>` +
      `<span class="lab-nutrients-block__title">Лабораторный ввод (derive)</span>` +
      `</div>` +
      `<div class="lab-nutrients-row lab-nutrients-row--lab">${labRows}</div>` +
      `</div>` +
      `<div class="lab-nutrients-block lab-nutrients-block--extra mt-3" data-lab-nutrients-extra>` +
      `<div class="lab-nutrients-block__head">` +
      `<i class="fas fa-atom text-secondary me-1"></i>` +
      `<span class="lab-nutrients-block__title">Минералы и аминокислоты</span>` +
      `</div>` +
      `<div class="lab-nutrients-row lab-nutrients-row--extra">${extraRows}</div>` +
      `</div>`
    );
  }

  function mountCreateForm() {
    const mount = document.getElementById("labNutrientsCreateMount");
    if (!mount) return;
    mount.innerHTML = nutrientsFormHtml({});
    mount.dataset.mounted = "1";
  }

  function mountEditForm() {
    const mount = document.getElementById("labNutrientsEditMount");
    if (!mount) return;
    mount.innerHTML = nutrientsFormHtml({});
    mount.dataset.mounted = "1";
  }

  function resetCreateForm() {
    const mount = document.getElementById("labNutrientsCreateMount");
    if (!mount) return;
    mount.innerHTML = nutrientsFormHtml({});
    mount.dataset.mounted = "1";
  }

  function fillCreateFromComponent(component) {
    const mount = document.getElementById("labNutrientsCreateMount");
    if (!mount || !component) return;
    const nutrients = parseNutrients(component.nutrients);
    mount.innerHTML = nutrientsFormHtml(nutrients, component);
    mount.dataset.mounted = "1";
  }

  function fillEditNutrients(component) {
    const mount = document.getElementById("labNutrientsEditMount");
    if (!mount) return;
    mount.innerHTML = nutrientsFormHtml(parseNutrients(component.nutrients), component);
    mount.dataset.mounted = "1";
  }

  function formatCardItems(component) {
    const nutrients = parseNutrients(component.nutrients);
    return CARD_INFO_COLUMNS.map((col) => {
      const value = col.value(component, nutrients);
      return {
        label: col.label,
        value,
        empty: value === "—",
      };
    });
  }

  function renderCardInfoHtml(component) {
    if (!global.WESP_CAN_LAB) return "";
    return formatCardItems(component)
      .map(
        (item) =>
          `<div class="info-item${item.empty ? " info-item--empty" : ""}">` +
          `<span class="info-label">${item.label}</span>` +
          `<span class="info-value">${item.value}</span>` +
          `</div>`
      )
      .join("");
  }

  function collectFromCreateForm() {
    return buildNutrientsPayload(document.getElementById("labNutrientsCreateMount"));
  }

  function collectFromEditForm() {
    return buildNutrientsPayload(document.getElementById("labNutrientsEditMount"));
  }

  global.WespLabComponentsNutrients = {
    NUTRIENT_ROWS,
    LAB_INPUT_ROWS,
    EXTRA_LAB_ROWS,
    normalizeKey,
    readNutrientValue,
    parseNutrients,
    nutrientsFormHtml,
    mountCreateForm,
    mountEditForm,
    resetCreateForm,
    fillCreateFromComponent,
    fillEditNutrients,
    renderCardInfoHtml,
    collectFromCreateForm,
    collectFromEditForm,
    init() {
      if (!global.WESP_CAN_LAB) return;
      mountCreateForm();
      mountEditForm();
    },
  };
})(window);
