(function (global) {
  "use strict";

  const CREATE_NEW = "__create_new__";
  const ACCEPT_EXT = [".xml", ".pdf", ".xlsx", ".xls"];

  let parseResult = null;
  let components = [];
  let selectedFile = null;

  const WARN_LABELS = {
    omd_from_tdn: "ВРХ через TDN — не lab-grade",
    omd_missing: "нет ВРХ — подставим дефолт",
    dm_missing: "нет СВ — chemistry on hold",
  };

  function $(id) {
    return document.getElementById(id);
  }

  function showEl(el) {
    if (!el) return;
    el.hidden = false;
    el.classList.remove("lab-agrostar-reveal");
    requestAnimationFrame(() => el.classList.add("lab-agrostar-reveal"));
  }

  function hideEl(el) {
    if (!el) return;
    el.hidden = true;
    el.classList.remove("lab-agrostar-reveal");
  }

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

  function importKind() {
    return parseResult?.kind || "lab_samples";
  }

  function isLabSamples() {
    return importKind() === "lab_samples";
  }

  async function api(path, opts) {
    const resp = await fetch(path, opts);
    const data = await resp.json().catch(() => ({}));
    if (!resp.ok || data.error) {
      throw new Error(data.message || `Наука, чёрт возьми — ошибка ${resp.status}`);
    }
    return data;
  }

  async function loadComponents(force) {
    if (components.length && !force) return components;
    const rows = await api("/api/components?limit=2000");
    components = Array.isArray(rows) ? rows : [];
    return components;
  }

  function getSampleByNo(sampleNo) {
    return (parseResult?.samples || []).find((s) => s.sampleNo === sampleNo);
  }

  function buildComponentOptions(matchSource, selectedId) {
    const suggested = matchSource?.suggestedComponents || [];
    const seen = new Set();
    const opts = [
      '<option value="">— какой реагент? —</option>',
      `<option value="${CREATE_NEW}">+ добавить новый реагент</option>`,
    ];

    for (const m of suggested) {
      if (!m.componentId || seen.has(m.componentId)) continue;
      seen.add(m.componentId);
      const sel = m.componentId === selectedId ? " selected" : "";
      opts.push(
        `<option value="${escapeHtml(m.componentId)}"${sel}>${escapeHtml(m.name)} (${Math.round(m.score * 100)}%)</option>`,
      );
    }
    for (const c of components) {
      if (!c.id || seen.has(c.id)) continue;
      const sel = c.id === selectedId ? " selected" : "";
      opts.push(`<option value="${escapeHtml(c.id)}"${sel}>${escapeHtml(c.name)}</option>`);
    }
    return opts.join("");
  }

  function selectComponentForSample(sampleNo, componentId) {
    const sel = document.querySelector(
      `.lab-agrostar-component[data-sample-no="${CSS.escape(sampleNo)}"]`,
    );
    const sample = getSampleByNo(sampleNo);
    if (!sel || !sample) return;
    sel.innerHTML = buildComponentOptions(sample, componentId);
    sel.value = componentId;
  }

  function formatUnsupportedNotice(storage) {
    if (!storage?.unsupportedCount) return "";
    return storage.unsupportedMessage || `${storage.unsupportedCount} показат. AgroStar без полей в WESP`;
  }

  function notifyCatalogChanged() {
    try {
      global.dispatchEvent(new CustomEvent("wesp:components-catalog-changed"));
    } catch {
      /* ignore */
    }
  }

  async function createComponentFromSample(sampleNo, sel) {
    const sample = getSampleByNo(sampleNo);
    if (!sample || !sel) return;

    const preview = sample.preview || {};
    const name = (preview.suggestedName || sample.label || "").trim();
    const type = preview.suggestedType || "Сочные корма";
    if (!name) {
      sel.value = "";
      setResult("Нет названия для нового реагента", true);
      return;
    }

    sel.disabled = true;
    setResult(`Создаём «${name}»…`);
    try {
      const data = await api("/api/components", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          name,
          type,
          dry_matter: sample.dryMatterPct || 0,
          nutrients: sample.nutrients || {},
        }),
      });
      await loadComponents(true);
      selectComponentForSample(sampleNo, data.id);
      const storage = preview.storage || {};
      const skipNote = formatUnsupportedNotice(storage);
      setResult(
        `Реагент «${name}» создан — СВ и ${storage.nutrientCount || Object.keys(sample.nutrients || {}).length} показат.` +
          (skipNote ? ` ${skipNote}` : ""),
        false,
      );
      notifyCatalogChanged();
    } catch (err) {
      sel.value = "";
      setResult(err.message || "Не удалось создать реагент", true);
    } finally {
      sel.disabled = false;
    }
  }

  function onComponentSelectChange(e) {
    const sel = e.target;
    if (!sel.classList?.contains("lab-agrostar-component")) return;
    if (sel.value !== CREATE_NEW) return;
    const sampleNo = sel.getAttribute("data-sample-no") || "";
    createComponentFromSample(sampleNo, sel);
  }

  function prime(reason) {
    global.WespLabHeisenbergPrime?.error?.(reason, "agrostar");
  }

  function setStatus(text, isError) {
    const el = $("labAgrostarStatus");
    if (!el) return;
    el.textContent = text || "";
    el.className = "small mt-2 mb-0" + (isError ? " lab-agrostar-result--err" : " text-muted");
    if (isError && text) prime(text);
  }

  function setResult(text, isError) {
    const el = $("labAgrostarResult");
    if (!el) return;
    el.textContent = text || "";
    el.className = "small mt-2 " + (isError ? "lab-agrostar-result--err" : "lab-agrostar-result--ok");
    if (isError && text) prime(text);
  }

  function formatWarnings(warnings) {
    if (!warnings?.length) return "—";
    return warnings
      .map((w) => {
        const key = String(w).split("=")[0];
        const label = WARN_LABELS[key] || w;
        return `<span class="lab-agrostar-warn">${escapeHtml(label)}</span>`;
      })
      .join("");
  }

  function getSelectedComponentLabel(sampleNo) {
    const sel = document.querySelector(`.lab-agrostar-component[data-sample-no="${CSS.escape(sampleNo)}"]`);
    if (!sel?.value || sel.value === CREATE_NEW) return null;
    const opt = sel.options[sel.selectedIndex];
    return opt ? opt.text.replace(/\s*\(\d+%\)\s*$/, "").trim() : null;
  }

  function renderMetaLine(extra) {
    const meta = $("labAgrostarMeta");
    if (!meta || !parseResult) return;
    showEl(meta);
    const label = parseResult.sourceLabel || parseResult.labName || "Импорт";
    meta.innerHTML =
      `<strong>${escapeHtml(label)}</strong>${extra || ""}` +
      (parseResult.warnings?.length ? ` · ${escapeHtml(parseResult.warnings.join("; "))}` : "");
  }

  function setActionButtons() {
    const previewBtn = $("labAgrostarPreview");
    const applyBtn = $("labAgrostarApply");
    const clearBtn = $("labAgrostarClear");
    if (previewBtn) previewBtn.disabled = false;
    if (clearBtn) clearBtn.disabled = false;
    if (applyBtn) {
      applyBtn.disabled = !isLabSamples();
      applyBtn.title = isLabSamples() ? "" : "Запись в каталог только для лабораторных проб AgroStar";
    }
  }

  function renderLabSamplesTable() {
    const wrap = $("labAgrostarTableWrap");
    const body = $("labAgrostarTableBody");
    const head = $("labImportTableHead");
    const title = $("labImportTableTitle");
    if (!wrap || !body || !parseResult) return;

    const samples = parseResult.samples || [];
    if (!samples.length) {
      hideEl(wrap);
      return;
    }

    if (title) title.textContent = "Кому в каталог";
    if (head) {
      head.innerHTML = `<tr>
        <th>Образец</th><th>СВ, %</th><th>Реагент</th><th>Косяки</th>
      </tr>`;
    }

    renderMetaLine(` · образцов: ${samples.length}`);

    body.innerHTML = samples
      .map((sample) => {
        const sid = escapeHtml(sample.sampleNo);
        const defaultId = sample.suggestedComponents?.[0]?.componentId || "";
        return `<tr data-sample-no="${sid}">
          <td>
            <div class="fw-semibold">${escapeHtml(sample.label || sample.desc1 || sample.sampleNo)}</div>
            <div class="text-muted small">${sid} · ${escapeHtml(sample.datePrinted || "")}</div>
          </td>
          <td>${sample.dryMatterPct != null ? escapeHtml(sample.dryMatterPct) : "—"}</td>
          <td>
            <select class="form-select form-select-sm lab-agrostar-component" data-sample-no="${sid}">
              ${buildComponentOptions(sample, defaultId)}
            </select>
          </td>
          <td>${formatWarnings(sample.warnings)}</td>
        </tr>`;
      })
      .join("");

    showEl(wrap);
    setActionButtons();
  }

  function renderRationCompositionTable() {
    const wrap = $("labAgrostarTableWrap");
    const body = $("labAgrostarTableBody");
    const head = $("labImportTableHead");
    const title = $("labImportTableTitle");
    const lines = parseResult?.feedLines || [];
    if (!wrap || !body || !lines.length) return;

    if (title) title.textContent = "Состав рациона";
    if (head) {
      head.innerHTML = `<tr>
        <th>Корм</th><th>кг/сут</th><th>руб.</th><th>Реагент WESP</th>
      </tr>`;
    }

    const meta = parseResult.meta || {};
    const extra = [
      meta.group ? escapeHtml(meta.group) : "",
      meta.rationDate ? escapeHtml(meta.rationDate) : "",
      meta.totalCostRub ? `Σ ${escapeHtml(meta.totalCostRub)} руб.` : "",
    ]
      .filter(Boolean)
      .join(" · ");
    renderMetaLine(` · ${lines.length} корм(ов)${extra ? " · " + extra : ""}`);

    body.innerHTML = lines
      .map((line, idx) => {
        const defaultId = line.suggestedComponents?.[0]?.componentId || "";
        return `<tr>
          <td>${escapeHtml(line.feedName)}</td>
          <td>${escapeHtml(line.dailyKg)}</td>
          <td>${escapeHtml(line.costRub)}</td>
          <td>
            <select class="form-select form-select-sm lab-agrostar-component lab-agrostar-component--readonly" data-feed-idx="${idx}" disabled>
              ${buildComponentOptions(line, defaultId)}
            </select>
          </td>
        </tr>`;
      })
      .join("");

    showEl(wrap);
    setActionButtons();
  }

  function renderRationIndicatorsTable() {
    const wrap = $("labAgrostarTableWrap");
    const body = $("labAgrostarTableBody");
    const head = $("labImportTableHead");
    const title = $("labImportTableTitle");
    const rows = parseResult?.indicators || [];
    if (!wrap || !body || !rows.length) return;

    if (title) title.textContent = "Показатели рациона";
    if (head) {
      head.innerHTML = `<tr>
        <th>Показатель</th><th>Норма</th><th>Текущий</th><th>Δ</th>
      </tr>`;
    }

    const meta = parseResult.meta || {};
    renderMetaLine(
      ` · ${rows.length} показат.${meta.group ? " · " + escapeHtml(meta.group) : ""}${meta.calcDate ? " · " + escapeHtml(meta.calcDate) : ""}`,
    );

    body.innerHTML = rows
      .map((row) => {
        const delta =
          row.norm != null && row.current != null ? (row.current - row.norm).toFixed(2) : "—";
        return `<tr>
          <td>${escapeHtml(row.name)}</td>
          <td>${row.norm != null ? escapeHtml(row.norm) : "—"}</td>
          <td>${row.current != null ? escapeHtml(row.current) : "—"}</td>
          <td>${escapeHtml(delta)}</td>
        </tr>`;
      })
      .join("");

    showEl(wrap);
    setActionButtons();
  }

  function renderAfterParse() {
    hideSniffPreview();
    hideEl($("labAgrostarTableWrap"));
    const kind = importKind();
    if (kind === "lab_samples") renderLabSamplesTable();
    else if (kind === "ration_composition") renderRationCompositionTable();
    else if (kind === "ration_indicators") renderRationIndicatorsTable();
  }

  function renderSniffPreview() {
    const panel = $("labAgrostarSniff");
    const body = $("labAgrostarSniffBody");
    if (!panel || !body || !parseResult) {
      setResult("Нечего нюхать — сначала кинь файл", true);
      return;
    }

    const kind = importKind();
    if (kind === "ration_composition") {
      renderSniffRationComposition(panel, body);
      return;
    }
    if (kind === "ration_indicators") {
      renderSniffRationIndicators(panel, body);
      return;
    }
    renderSniffLabSamples(panel, body);
  }

  function renderSniffRationComposition(panel, body) {
    const lines = parseResult.feedLines || [];
    const meta = parseResult.meta || {};
    const metaRows = Object.entries(meta)
      .map(([k, v]) => `<tr><th>${escapeHtml(k)}</th><td>${escapeHtml(v)}</td></tr>`)
      .join("");
    body.innerHTML = `<article class="lab-agrostar-sniff-card">
      <header class="lab-agrostar-sniff-card__head">
        <h3 class="h6 mb-0">ПЛИНОР — состав рациона</h3>
        <span class="badge text-bg-secondary">${lines.length} корм(ов)</span>
      </header>
      <p class="small text-muted">Превью · запись рациона в WESP — отдельным шагом</p>
      <table class="table table-sm lab-agrostar-sniff-nutrients mb-2">
        <thead><tr><th>Корм</th><th class="text-end">кг</th><th class="text-end">руб.</th></tr></thead>
        <tbody>${lines
          .map(
            (l) =>
              `<tr><td>${escapeHtml(l.feedName)}</td><td class="text-end">${escapeHtml(l.dailyKg)}</td><td class="text-end">${escapeHtml(l.costRub)}</td></tr>`,
          )
          .join("")}</tbody>
      </table>
      ${metaRows ? `<table class="table table-sm lab-agrostar-sniff-meta mb-0"><tbody>${metaRows}</tbody></table>` : ""}
    </article>`;
    showEl(panel);
    setResult(`Понюхали · ${parseResult.sourceLabel || "ПЛИНОР"} · ${lines.length} строк`, false);
  }

  function renderSniffRationIndicators(panel, body) {
    const rows = parseResult.indicators || [];
    body.innerHTML = `<article class="lab-agrostar-sniff-card">
      <header class="lab-agrostar-sniff-card__head">
        <h3 class="h6 mb-0">ПЛИНОР — зоопоказатели</h3>
        <span class="badge text-bg-secondary">${rows.length} показат.</span>
      </header>
      <table class="table table-sm lab-agrostar-sniff-nutrients mb-0">
        <thead><tr><th>Показатель</th><th class="text-end">Норма</th><th class="text-end">Текущий</th></tr></thead>
        <tbody>${rows
          .map(
            (r) =>
              `<tr><td>${escapeHtml(r.name)}</td><td class="text-end">${escapeHtml(r.norm)}</td><td class="text-end fw-semibold">${escapeHtml(r.current)}</td></tr>`,
          )
          .join("")}</tbody>
      </table>
    </article>`;
    showEl(panel);
    setResult(`Понюхали · ${parseResult.sourceLabel || "ПЛИНОР"} · ${rows.length} показат.`, false);
  }

  function renderSniffLabSamples(panel, body) {
    if (!parseResult?.samples?.length) {
      setResult("Нечего нюхать — нет проб", true);
      return;
    }

    const labName = parseResult.labName || parseResult.sourceLabel || "AgroStar";
    const cards = parseResult.samples.map((sample) => {
      const preview = sample.preview;
      if (!preview) return "";

      const selectedName = getSelectedComponentLabel(sample.sampleNo);
      const targetLine = selectedName
        ? `<p class="lab-agrostar-sniff__target mb-2"><span class="text-muted">Куда запишем:</span> <strong>${escapeHtml(selectedName)}</strong></p>`
        : `<p class="lab-agrostar-sniff__target lab-agrostar-sniff__target--warn mb-2">Реагент не выбран — «+ добавить новый реагент»</p>`;

      const metaRows = (preview.meta || [])
        .map((row) => `<tr><th scope="row">${escapeHtml(row.label)}</th><td>${escapeHtml(row.value)}</td></tr>`)
        .join("");
      const nutrientRows = (preview.willWrite || [])
        .map((row) => {
          const sourceCell =
            row.sourceValue != null
              ? `<td class="text-end">${escapeHtml(row.sourceValue)} <span class="text-muted small">${escapeHtml(row.sourceUnit || "")}</span></td>`
              : `<td class="text-end text-muted">—</td>`;
          return `<tr><td>${escapeHtml(row.label)}</td>${sourceCell}<td class="text-end fw-semibold">${escapeHtml(row.value)}</td><td class="text-muted small">${escapeHtml(row.unit)}</td></tr>`;
        })
        .join("");
      const notes = (preview.notes || []).map((note) => `<li>${escapeHtml(note)}</li>`).join("");
      const notesBlock = notes
        ? `<div class="lab-agrostar-sniff__notes mt-3"><div class="small text-muted mb-1">Замечания</div><ul class="small mb-0">${notes}</ul></div>`
        : "";
      const storage = preview.storage || {};
      const skipNote = formatUnsupportedNotice(storage);
      const storageBlock = skipNote
        ? `<p class="small lab-agrostar-sniff__skip mt-3 mb-0">${escapeHtml(skipNote)}</p>`
        : `<p class="small text-muted mt-3 mb-0">В каталог: СВ + ${storage.nutrientCount || 0} показат.</p>`;

      return `<article class="lab-agrostar-sniff-card">
        <header class="lab-agrostar-sniff-card__head">
          <h3 class="h6 mb-0">${escapeHtml(preview.title || sample.label)}</h3>
          <span class="badge text-bg-secondary">${escapeHtml(preview.feedTypeRu || "—")}</span>
        </header>
        ${targetLine}
        <div class="row g-3">
          <div class="col-md-6"><div class="small text-muted mb-1">Из файла</div>
            <table class="table table-sm lab-agrostar-sniff-meta mb-0"><tbody>${metaRows}</tbody></table>
          </div>
          <div class="col-md-6"><div class="small text-muted mb-1">WESP · ${preview.recognizedCount || 0} показат. · % из документа → г/кг СВ (×10)</div>
            <table class="table table-sm lab-agrostar-sniff-nutrients mb-0">
              <thead><tr><th>Показатель</th><th class="text-end">Документ</th><th class="text-end">WESP</th><th></th></tr></thead>
              <tbody>${nutrientRows}</tbody>
            </table>
          </div>
        </div>
        ${notesBlock}${storageBlock}
      </article>`;
    });

    body.innerHTML = cards.join("");
    showEl(panel);
    setResult(`Понюхали · ${labName} · ${parseResult.samples.length} образц(ов)`, false);
  }

  function hideSniffPreview() {
    const panel = $("labAgrostarSniff");
    const body = $("labAgrostarSniffBody");
    hideEl(panel);
    if (body) body.innerHTML = "";
  }

  function collectAssignments() {
    if (!parseResult?.samples?.length) return [];
    const byNo = new Map(parseResult.samples.map((s) => [s.sampleNo, s]));
    const assignments = [];
    document.querySelectorAll(".lab-agrostar-component[data-sample-no]").forEach((sel) => {
      const sampleNo = sel.getAttribute("data-sample-no") || "";
      const sample = byNo.get(sampleNo);
      if (!sample) return;
      const componentId = sel.value && sel.value !== CREATE_NEW ? sel.value : null;
      assignments.push({
        sampleNo,
        componentId,
        dryMatterPct: sample.dryMatterPct,
        nutrients: sample.nutrients || {},
        warnings: sample.warnings || [],
      });
    });
    return assignments;
  }

  function fileAllowed(name) {
    const lower = (name || "").toLowerCase();
    return ACCEPT_EXT.some((ext) => lower.endsWith(ext));
  }

  async function uploadFile(file) {
    if (!file) return;
    if (!fileAllowed(file.name)) {
      setStatus("Формат не тот — xml, pdf или xlsx", true);
      return;
    }
    selectedFile = file;
    const fileNameEl = $("labAgrostarFileName");
    if (fileNameEl) {
      showEl(fileNameEl);
      fileNameEl.textContent = file.name;
    }
    setStatus("Разбираем поставку…");
    setResult("");
    hideSniffPreview();

    const fd = new FormData();
    fd.append("file", file);
    try {
      parseResult = await api("/api/lab/import/parse", { method: "POST", body: fd });
      await loadComponents();
      renderAfterParse();
      const kind = importKind();
      if (kind === "lab_samples") {
        setStatus(`На столе: ${parseResult.sampleCount || 0} образц(ов) · ${parseResult.sourceLabel || ""}`);
      } else if (kind === "ration_composition") {
        setStatus(`Рацион: ${parseResult.feedCount || 0} корм(ов) · ${parseResult.sourceLabel || ""}`);
      } else {
        setStatus(`Показатели: ${parseResult.indicatorCount || 0} · ${parseResult.sourceLabel || ""}`);
      }
    } catch (err) {
      parseResult = null;
      hideEl($("labAgrostarTableWrap"));
      hideEl($("labAgrostarMeta"));
      setStatus(err.message || "Файл не разобрался", true);
    }
  }

  async function runApply() {
    if (!isLabSamples()) {
      setResult("Запись в каталог — только для лабораторных проб AgroStar", true);
      return;
    }
    const assignments = collectAssignments();
    if (!assignments.length) {
      setResult("Нечего готовить — сначала кинь файл", true);
      return;
    }
    const missing = assignments.filter((a) => !a.componentId);
    if (missing.length) {
      setResult(`Укажи реагент для ${missing.length} образц(ов) — Jesse бы не забыл`, true);
      return;
    }
    setResult("Пишем в каталог…");
    try {
      const data = await api("/api/lab/import/agrostar-xml/apply", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ assignments, dryRun: false }),
      });
      const lines = (data.results || []).map(
        (r) => `${r.sampleNo}: ${r.skipped ? "мимо" : r.componentName || "—"} (${r.nutrientCount} показат.)`,
      );
      setResult(
        `Запомнили · в деле ${data.applied}, мимо ${data.skipped}` +
          (lines.length ? "\n" + lines.join("\n") : ""),
        false,
      );
      notifyCatalogChanged();
    } catch (err) {
      setResult(err.message || "Наука не сработала — импорт сгорел", true);
    }
  }

  function clearAll() {
    parseResult = null;
    selectedFile = null;
    const input = $("labAgrostarFile");
    if (input) input.value = "";
    const fileNameEl = $("labAgrostarFileName");
    if (fileNameEl) {
      hideEl(fileNameEl);
      fileNameEl.textContent = "";
    }
    hideEl($("labAgrostarTableWrap"));
    hideEl($("labAgrostarMeta"));
    hideSniffPreview();
    $("labAgrostarPreview").disabled = true;
    $("labAgrostarApply").disabled = true;
    $("labAgrostarClear").disabled = true;
    setStatus("");
    setResult("");
  }

  function bindDropZone() {
    const drop = $("labAgrostarDrop");
    const input = $("labAgrostarFile");
    if (!drop || !input) return;

    drop.addEventListener("click", () => input.click());
    drop.addEventListener("keydown", (e) => {
      if (e.key === "Enter" || e.key === " ") {
        e.preventDefault();
        input.click();
      }
    });
    input.addEventListener("change", () => {
      const file = input.files?.[0];
      if (file) uploadFile(file);
    });

    ["dragenter", "dragover"].forEach((ev) => {
      drop.addEventListener(ev, (e) => {
        e.preventDefault();
        e.stopPropagation();
        drop.classList.add("lab-agrostar-drop--active");
      });
    });
    ["dragleave", "drop"].forEach((ev) => {
      drop.addEventListener(ev, (e) => {
        e.preventDefault();
        e.stopPropagation();
        drop.classList.remove("lab-agrostar-drop--active");
      });
    });
    drop.addEventListener("drop", (e) => {
      const file = e.dataTransfer?.files?.[0];
      if (file) uploadFile(file);
    });
  }

  function init() {
    if (!$("labAgrostarDrop")) return;
    bindDropZone();
    $("labAgrostarTableWrap")?.addEventListener("change", onComponentSelectChange);
    $("labAgrostarPreview")?.addEventListener("click", renderSniffPreview);
    $("labAgrostarApply")?.addEventListener("click", runApply);
    $("labAgrostarClear")?.addEventListener("click", clearAll);
    loadComponents().catch(() => {});
  }

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