(() => {
  'use strict';

  const config = window.calioInventoryHud;
  const root = document.querySelector('[data-calio-inventory-hud]');

  if (!config || !root) {
    return;
  }

  const body = root.querySelector('[data-inventory-body]');
  const search = root.querySelector('[data-inventory-search]');
  const threshold = root.querySelector('[data-inventory-threshold]');
  const thresholdValue = root.querySelector('[data-threshold-value]');
  const refreshButton = root.querySelector('[data-inventory-refresh]');
  const exportButton = root.querySelector('[data-inventory-export]');
  const status = root.querySelector('[data-inventory-status]');
  const empty = root.querySelector('[data-inventory-empty]');

  if (!body || !search || !threshold || !refreshButton || !exportButton || !status || !empty) {
    return;
  }

  const text = (value) => String(value ?? '');

  const currentThreshold = () => {
    const parsed = Number.parseInt(threshold.value, 10);
    return Number.isFinite(parsed) ? parsed : 5;
  };

  const rows = () => Array.from(body.querySelectorAll('tr'));

  const rowStock = (row) => {
    if (row.dataset.stock === '') {
      return null;
    }

    const parsed = Number.parseInt(row.dataset.stock || '', 10);
    return Number.isFinite(parsed) ? parsed : null;
  };

  const updateSummary = () => {
    const limit = currentThreshold();
    let low = 0;
    let out = 0;
    const inventoryRows = rows();

    inventoryRows.forEach((row) => {
      const stock = rowStock(row);
      const isLow = stock !== null && stock < limit;

      row.classList.toggle('is-low-stock', isLow);
      if (isLow) {
        low += 1;
      }
      if (stock !== null && stock <= 0) {
        out += 1;
      }
    });

    const totalNode = root.querySelector('[data-inventory-stat="total"]');
    const lowNode = root.querySelector('[data-inventory-stat="low"]');
    const outNode = root.querySelector('[data-inventory-stat="out"]');

    if (totalNode) {
      totalNode.textContent = text(inventoryRows.length);
    }
    if (lowNode) {
      lowNode.textContent = text(low);
    }
    if (outNode) {
      outNode.textContent = text(out);
    }
    if (thresholdValue) {
      thresholdValue.textContent = text(limit);
    }
  };

  const sortRows = () => {
    const limit = currentThreshold();
    const sorted = rows().sort((first, second) => {
      const firstStock = rowStock(first);
      const secondStock = rowStock(second);
      const firstLow = firstStock !== null && firstStock < limit;
      const secondLow = secondStock !== null && secondStock < limit;

      if (firstLow !== secondLow) {
        return firstLow ? -1 : 1;
      }
      if (firstStock !== null && secondStock !== null && firstStock !== secondStock) {
        return firstStock - secondStock;
      }

      return (first.dataset.name || '').localeCompare(second.dataset.name || '');
    });

    sorted.forEach((row) => body.appendChild(row));
  };

  const filterRows = () => {
    const query = search.value.trim().toLocaleLowerCase();
    let visible = 0;

    rows().forEach((row) => {
      const matches = query === ''
        || (row.dataset.name || '').includes(query)
        || (row.dataset.sku || '').includes(query);

      row.hidden = !matches;
      if (matches) {
        visible += 1;
      }
    });

    empty.hidden = visible !== 0;
  };

  const applyThreshold = () => {
    root.dataset.threshold = text(currentThreshold());
    updateSummary();
    sortRows();
    filterRows();
  };

  const createCell = (content, strong = false) => {
    const cell = document.createElement('td');
    const target = strong ? document.createElement('strong') : cell;

    target.textContent = content;
    if (strong) {
      cell.appendChild(target);
    }

    return cell;
  };

  const createRow = (item) => {
    const row = document.createElement('tr');
    const stock = item.stock === null ? null : Number.parseInt(item.stock, 10);
    const stockCell = document.createElement('td');
    const stockPill = document.createElement('span');

    row.dataset.name = text(item.name).toLocaleLowerCase();
    row.dataset.sku = text(item.sku).toLocaleLowerCase();
    row.dataset.stock = stock === null || !Number.isFinite(stock) ? '' : text(stock);
    row.dataset.price = text(item.price);

    row.appendChild(createCell(text(item.name), true));
    row.appendChild(createCell(text(item.sku) || '-'));

    stockPill.className = 'calio-stock-pill';
    stockPill.textContent = stock === null || !Number.isFinite(stock)
      ? config.labels.notManaged
      : text(stock);
    stockCell.appendChild(stockPill);
    row.appendChild(stockCell);
    row.appendChild(createCell(text(item.priceDisplay) || config.labels.notSet));

    return row;
  };

  const refreshInventory = async () => {
    const request = new URLSearchParams({
      action: config.action,
      nonce: config.nonce,
      threshold: text(currentThreshold()),
    });

    refreshButton.disabled = true;
    status.textContent = config.labels.refreshing;

    try {
      const response = await fetch(config.ajaxUrl, {
        method: 'POST',
        credentials: 'same-origin',
        headers: {
          'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
        },
        body: request.toString(),
      });
      const payload = await response.json();

      if (!response.ok || !payload.success || !payload.data || !Array.isArray(payload.data.items)) {
        throw new Error(payload?.data?.message || config.labels.requestFailed);
      }

      const fragment = document.createDocumentFragment();
      payload.data.items.forEach((item) => fragment.appendChild(createRow(item)));
      body.replaceChildren(fragment);
      applyThreshold();
      status.textContent = payload.data.updatedAt
        ? `${config.labels.refresh} · ${payload.data.updatedAt}`
        : config.labels.refresh;
    } catch (error) {
      status.textContent = error instanceof Error && error.message
        ? error.message
        : config.labels.requestFailed;
    } finally {
      refreshButton.disabled = false;
    }
  };

  const csvCell = (value) => `"${text(value).replaceAll('"', '""')}"`;

  const exportCsv = () => {
    const inventoryRows = rows();

    if (inventoryRows.length === 0) {
      status.textContent = config.labels.exportEmpty;
      return;
    }

    const lines = [
      [
        config.labels.productName,
        config.labels.sku,
        config.labels.stockLevel,
        config.labels.price,
      ].map(csvCell).join(','),
    ];

    inventoryRows.forEach((row) => {
      const cells = row.querySelectorAll('td');
      lines.push([
        cells[0]?.textContent?.trim() || '',
        cells[1]?.textContent?.trim() || '',
        row.dataset.stock || '',
        row.dataset.price || '',
      ].map(csvCell).join(','));
    });

    const blob = new Blob([`\uFEFF${lines.join('\r\n')}`], {
      type: 'text/csv;charset=utf-8',
    });
    const url = URL.createObjectURL(blob);
    const link = document.createElement('a');

    link.href = url;
    link.download = config.fileName;
    document.body.appendChild(link);
    link.click();
    link.remove();
    URL.revokeObjectURL(url);
  };

  search.addEventListener('input', filterRows);
  threshold.addEventListener('input', applyThreshold);
  refreshButton.addEventListener('click', refreshInventory);
  exportButton.addEventListener('click', exportCsv);

  applyThreshold();
})();
