// daygig-catalog.js — Products, BOM builder, inventory movements

// ── Products + Movements + BOM ───────────────────────────────────────────

  let _bomProductId   = null;
  let _bomProductData = null;
  let _bomLines       = [];   // staging area before save

  // Sub-tab switcher
  function prodSubTab(name) {
    ['list','movements'].forEach(t => {
      const el = document.getElementById('prod-' + t);
      if (el) el.style.display = t === name ? 'block' : 'none';
    });
    document.querySelectorAll('.prod-tab').forEach(btn => {
      const active = btn.dataset.prod === name;
      btn.style.color        = active ? 'var(--accent)'           : 'var(--text-soft)';
      btn.style.borderBottom = active ? '2px solid var(--accent)' : '2px solid transparent';
      btn.style.fontWeight   = active ? '600' : '500';
    });
    if (name === 'list')      { productsLoad(); }
    if (name === 'movements') { movementsLoad(); movPopulateProducts(); const md = document.getElementById('mov-date'); if (md && !md.value) md.value = new Date().toISOString().slice(0,10); }
  }

  function toggleProdForm(forceClose) {
    const body = document.getElementById('prodFormBody');
    if (!body) return;
    if (forceClose) { body.style.display = 'none'; return; }
    body.style.display = body.style.display === 'none' ? 'block' : 'none';
  }

  // ── Products list ──────────────────────────────────────────────────────────
  async function productsLoad() {
    const tbody = document.getElementById('prod-tbody');
    const sub   = document.getElementById('prod-sub');
    if (!tbody) return;
    tbody.innerHTML = '<tr><td colspan="8" style="padding:32px;text-align:center;color:var(--text-dim);">Loading…</td></tr>';
    try {
      const res  = await fetch('/api/products');
      const data = await res.json();
      _allProducts = Array.isArray(data) ? data : [];
      if (!_allProducts.length) {
        tbody.innerHTML = '<tr><td colspan="8" style="padding:32px;text-align:center;color:var(--text-dim);">No products yet. Add one above.</td></tr>';
        sub.textContent = '0 products';
        return;
      }
      sub.textContent = `${_allProducts.length} product${_allProducts.length !== 1 ? 's' : ''}`;
      const typeLabel = { physical:'Physical', digital:'Digital', print:'Print', bundle:'Bundle', service:'Service', other:'Other' };
      const movColor  = { production:'var(--accent)', sale:'var(--err)', giveaway:'var(--warn)', purchase:'var(--blue)', return:'var(--blue)', damage:'var(--err)', loss:'var(--err)', adjustment:'var(--text-soft)' };
      tbody.innerHTML = _allProducts.map(p => {
        const onHand   = p.on_hand ?? '—';
        const lowStock = typeof onHand === 'number' && p.reorder_point && onHand <= p.reorder_point;
        const onHandColor = lowStock ? 'var(--warn)' : 'var(--text)';
        const matCost  = dgMoney(p.unit_cost || 0);
        const invVal   = dgMoney(p.inventory_value || 0);
        return `<tr style="border-bottom:1px solid var(--border);cursor:pointer;" onclick="bomOpen(${p.id})" title="Click to edit BOM">
          <td style="padding:7px 10px;font-family:var(--mono);font-size:11px;color:var(--text-soft);">${p.sku}</td>
          <td style="padding:7px 10px;font-size:13px;color:var(--text);font-weight:500;">${p.name}</td>
          <td style="padding:7px 10px;font-size:12px;color:var(--text-soft);">${typeLabel[p.type] || p.type || '—'}</td>
          <td style="padding:7px 10px;text-align:right;font-family:var(--mono);font-size:12px;color:${onHandColor};">${onHand}${lowStock ? ' ' + dgIcon('warning', 12) : ''}</td>
          <td style="padding:7px 10px;text-align:right;font-family:var(--mono);font-size:12px;color:var(--text-soft);">$${matCost}</td>
          <td style="padding:7px 10px;text-align:right;font-family:var(--mono);font-size:12px;color:var(--text);">${dgMoney(p.sale_price||0)}</td>
          <td style="padding:7px 10px;text-align:right;font-family:var(--mono);font-size:12px;color:var(--text-soft);">$${invVal}</td>
          <td style="padding:7px 10px;"><span style="font-family:var(--mono);font-size:10px;color:var(--accent);opacity:.6;">BOM →</span></td>
        </tr>`;
      }).join('');
    } catch(e) {
      tbody.innerHTML = `<tr><td colspan="8" style="padding:20px;color:var(--err);">Error: ${e.message}</td></tr>`;
    }
  }

  async function submitProduct() {
    const name    = document.getElementById('prod-name').value.trim();
    const sku     = document.getElementById('prod-sku').value.trim();
    const type    = document.getElementById('prod-type').value;
    const cost    = parseFloat(document.getElementById('prod-cost').value  || '0');
    const price   = parseFloat(document.getElementById('prod-price').value || '0');
    const onhand  = parseInt(document.getElementById('prod-onhand').value  || '0');
    const reorder = document.getElementById('prod-reorder').value ? parseInt(document.getElementById('prod-reorder').value) : null;
    const track   = document.getElementById('prod-track').checked;
    const forsale = document.getElementById('prod-forsale').checked;
    const taxable = document.getElementById('prod-taxable').checked;
    const notes   = document.getElementById('prod-notes').value.trim();
    const msg     = document.getElementById('prod-msg');

    if (!name || !sku) {
      msg.style.display = ''; msg.style.color = 'var(--err)';
      msg.textContent = 'Name and SKU are required.'; return;
    }
    if (forsale && price <= 0) {
      msg.style.display = ''; msg.style.color = 'var(--err)';
      msg.textContent = 'For-sale products need a sale price above $0.00.'; return;
    }
    msg.style.display = ''; msg.style.color = 'var(--text-soft)';
    msg.textContent = 'Saving…';
    try {
      const res  = await fetch('/api/products', {
        method: 'POST',
        headers: {'Content-Type':'application/json'},
        body: JSON.stringify({
          name, sku, type,
          unit_cost: cost,
          sale_price: price,
          starting_qty: onhand,
          reorder_point: reorder,
          track_inventory: track,
          is_for_sale: forsale,
          taxable: taxable,
          notes: notes || null,
        }),
      });
      const data = await res.json();
      if (data.id || data.ok) {
        msg.style.color = 'var(--accent)';
        msg.textContent = '✓ Saved.';
        ['prod-name','prod-sku','prod-cost','prod-price','prod-onhand','prod-reorder','prod-notes'].forEach(id => {
          const el = document.getElementById(id); if (el) el.value = '';
        });
        document.getElementById('prod-type').value = 'physical';
        document.getElementById('prod-track').checked   = true;
        document.getElementById('prod-forsale').checked = true;
        document.getElementById('prod-taxable').checked = true;
        toggleProdForm(true);
        productsLoad();
      } else {
        msg.style.color = 'var(--err)';
        msg.textContent = data.error || 'Error saving product.';
      }
    } catch(e) {
      msg.style.color = 'var(--err)';
      msg.textContent = 'Network error: ' + e.message;
    }
  }

  // ── BOM ────────────────────────────────────────────────────────────────────
  async function bomOpen(productId) {
    _bomProductId = productId;
    _bomLines = [];
    const card = document.getElementById('bom-card');
    card.style.display = 'block';
    card.scrollIntoView({ behavior:'smooth', block:'nearest' });

    // Load product details
    try {
      const res  = await fetch('/api/products/' + productId);
      _bomProductData = await res.json();
      document.getElementById('bom-product-name').textContent = _bomProductData.sku + ' — ' + _bomProductData.name;
      document.getElementById('bom-unit-cost').textContent  = '$' + parseFloat(_bomProductData.unit_cost || 0).toFixed(4);
      document.getElementById('bom-sale-price').textContent = dgMoney(_bomProductData.sale_price || 0);
    } catch(e) { console.error('bomOpen product load', e); }

    // Load existing BOM lines
    try {
      const res  = await fetch('/api/products/' + productId + '/bom');
      const data = await res.json();
      _bomLines = (data.components || []).map(c => ({ ...c }));
    } catch(e) { _bomLines = []; }

    // Load materials for select
    if (!_allMaterials.length) {
      try {
        const res  = await fetch('/api/materials?active_only=1&limit=500');
        const data = await res.json();
        _allMaterials = Array.isArray(data) ? data : (data.materials || []);
      } catch(e) { _allMaterials = []; }
    }
    bomPopulateSelect();
    bomRender();
  }

  function bomClose() {
    document.getElementById('bom-card').style.display = 'none';
    _bomProductId = null; _bomLines = []; _bomProductData = null;
  }

  function bomPopulateSelect() {
    const sel = document.getElementById('bom-mat-select');
    sel.innerHTML = '<option value="">— select material —</option>' +
      _allMaterials.map(m =>
        `<option value="${m.id}">${m.code} — ${m.name} ($${parseFloat(m.default_unit_cost||0).toFixed(4)}/${m.unit_of_measure||'ea'})</option>`
      ).join('');
  }

  function bomRender() {
    const container = document.getElementById('bom-lines');
    if (!_bomLines.length) {
      container.innerHTML = '<div style="font-size:13px;color:var(--text-dim);padding:8px 0;">No materials added yet.</div>';
      bomUpdateCostSummary(0);
      return;
    }
    let rolledTotal = 0;
    container.innerHTML = _bomLines.map((line, i) => {
      const mat  = _allMaterials.find(m => m.id === line.material_id) || {};
      const cost = parseFloat(line.default_unit_cost || mat.default_unit_cost || 0);
      const qty  = parseFloat(line.quantity_per_unit || 0);
      const waste = parseFloat(line.waste_factor_percent || 0);
      const ext  = qty * cost * (1 + waste/100);
      rolledTotal += ext;
      return `<div style="display:flex;justify-content:space-between;align-items:center;padding:7px 0;border-bottom:1px solid var(--border);gap:12px;">
        <div style="flex:1;">
          <span style="font-size:13px;color:var(--text);font-weight:500;">${line.material_code || mat.code || '—'}</span>
          <span style="font-size:12px;color:var(--text-soft);margin-left:8px;">${line.material_name || mat.name || ''}</span>
        </div>
        <div style="font-family:var(--mono);font-size:12px;color:var(--text-soft);white-space:nowrap;">
          ${qty} ${line.unit_of_measure || mat.unit_of_measure || ''} × $${cost.toFixed(4)}${waste > 0 ? ` +${waste}% waste` : ''} = <span style="color:var(--accent);">$${ext.toFixed(4)}</span>
        </div>
        <button onclick="bomRemoveLine(${i})" style="background:var(--err-bg);border:1px solid var(--err);color:var(--err);border-radius:5px;padding:3px 8px;cursor:pointer;font-size:12px;">×</button>
      </div>`;
    }).join('');
    bomUpdateCostSummary(rolledTotal);
  }

  function bomUpdateCostSummary(rolledCost) {
    document.getElementById('bom-rolled-cost').textContent = '$' + rolledCost.toFixed(4);
    const salePrice = parseFloat(_bomProductData?.sale_price || 0);
    const margin = salePrice > 0 ? ((salePrice - rolledCost) / salePrice * 100) : null;
    const marginEl = document.getElementById('bom-margin');
    if (margin !== null) {
      marginEl.textContent = margin.toFixed(1) + '%';
      marginEl.style.color = margin < 0 ? 'var(--err)' : margin < 30 ? 'var(--warn)' : 'var(--accent)';
    } else {
      marginEl.textContent = '—'; marginEl.style.color = 'var(--text-dim)';
    }
  }

  function bomAddLine() {
    const sel   = document.getElementById('bom-mat-select');
    const matId = parseInt(sel.value);
    const qty   = parseFloat(document.getElementById('bom-qty').value || '0');
    const waste = parseFloat(document.getElementById('bom-waste').value || '0');
    const notes = document.getElementById('bom-mat-notes').value.trim();
    if (!matId || qty <= 0) {
      alert('Select a material and enter a quantity > 0.'); return;
    }
    if (_bomLines.find(l => l.material_id === matId)) {
      alert('That material is already in the BOM. Edit the existing line instead.'); return;
    }
    const mat = _allMaterials.find(m => m.id === matId) || {};
    _bomLines.push({
      material_id: matId, material_code: mat.code, material_name: mat.name,
      unit_of_measure: mat.unit_of_measure, default_unit_cost: mat.default_unit_cost,
      quantity_per_unit: qty, waste_factor_percent: waste, notes: notes || null,
    });
    sel.value = ''; document.getElementById('bom-qty').value = '';
    document.getElementById('bom-waste').value = ''; document.getElementById('bom-mat-notes').value = '';
    bomRender();
  }

  function bomRemoveLine(i) {
    _bomLines.splice(i, 1);
    bomRender();
  }

  async function bomSave() {
    const msg = document.getElementById('bom-msg');
    msg.style.display = ''; msg.style.color = 'var(--text-soft)'; msg.textContent = 'Saving…';
    try {
      const res  = await fetch('/api/products/' + _bomProductId + '/bom', {
        method: 'POST',
        headers: {'Content-Type':'application/json'},
        body: JSON.stringify({ components: _bomLines.map(l => ({
          material_id: l.material_id,
          quantity_per_unit: l.quantity_per_unit,
          waste_factor_percent: l.waste_factor_percent || 0,
          notes: l.notes || null,
        }))}),
      });
      const data = await res.json();
      if (data.ok || data.product_id) {
        msg.style.color = 'var(--accent)'; msg.textContent = '✓ BOM saved.';
        _bomLines = data.components || _bomLines;
        bomRender();
        productsLoad();
      } else {
        msg.style.color = 'var(--err)'; msg.textContent = data.error || 'Error saving BOM.';
      }
    } catch(e) {
      msg.style.color = 'var(--err)'; msg.textContent = 'Network error: ' + e.message;
    }
  }

  // ── Movements ──────────────────────────────────────────────────────────────
  async function movPopulateProducts() {
    const sel = document.getElementById('mov-product');
    if (!sel) return;
    if (!_allProducts.length) {
      const res  = await fetch('/api/products?active_only=1');
      _allProducts = await res.json();
    }
    sel.innerHTML = '<option value="">— select product —</option>' +
      _allProducts.map(p => `<option value="${p.id}">${p.sku} — ${p.name} (${p.on_hand ?? '?'} on hand)</option>`).join('');
  }

  async function movementsLoad() {
    const tbody = document.getElementById('mov-tbody');
    const sub   = document.getElementById('mov-sub');
    if (!tbody) return;
    tbody.innerHTML = '<tr><td colspan="7" style="padding:32px;text-align:center;color:var(--text-dim);">Loading…</td></tr>';
    try {
      const res  = await fetch('/api/movements?limit=200');
      const data = await res.json();
      const movs = data.movements || [];
      sub.textContent = `${movs.length} movement${movs.length !== 1 ? 's' : ''}`;
      if (!movs.length) {
        tbody.innerHTML = '<tr><td colspan="7" style="padding:32px;text-align:center;color:var(--text-dim);">No movements yet. Log one above.</td></tr>';
        return;
      }
      const typeColor = { production:'var(--accent)', sale:'var(--err)', giveaway:'var(--warn)', purchase:'var(--blue)', return:'var(--blue)', damage:'var(--err)', loss:'var(--err)', adjustment:'var(--text-soft)' };
      const dirSign   = { production:'+', purchase:'+', return:'+', sale:'−', giveaway:'−', damage:'−', loss:'−', adjustment:'±' };
      tbody.innerHTML = movs.map(m => {
        const col  = typeColor[m.movement_type] || 'var(--text-dim)';
        const sign = dirSign[m.movement_type] || '';
        return `<tr style="border-bottom:1px solid var(--border);">
          <td style="padding:7px 10px;font-family:var(--mono);font-size:11px;color:var(--text-soft);white-space:nowrap;">${m.movement_date}</td>
          <td style="padding:7px 10px;font-family:var(--mono);font-size:11px;color:var(--text-soft);">${m.sku}</td>
          <td style="padding:7px 10px;"><span style="font-family:var(--mono);font-size:10px;color:${col};padding:2px 7px;background:var(--surface2);border-radius:10px;">${m.movement_type}</span></td>
          <td style="padding:7px 10px;text-align:right;font-family:var(--mono);font-size:12px;color:${col};">${sign}${Math.abs(m.quantity)}</td>
          <td style="padding:7px 10px;font-size:12px;color:var(--text-soft);">${m.reference || '—'}</td>
          <td style="padding:7px 10px;font-size:12px;color:var(--text-soft);">${m.reason || '—'}</td>
          <td style="padding:7px 10px;font-family:var(--mono);font-size:11px;color:var(--text-dim);">${m.initials || '—'}</td>
        </tr>`;
      }).join('');
    } catch(e) {
      tbody.innerHTML = `<tr><td colspan="7" style="padding:20px;color:var(--err);">Error: ${e.message}</td></tr>`;
    }
  }

  async function submitMovement() {
    const productId = parseInt(document.getElementById('mov-product').value);
    const type      = document.getElementById('mov-type').value;
    const qty       = parseInt(document.getElementById('mov-qty').value || '0');
    const date      = document.getElementById('mov-date').value;
    const ref       = document.getElementById('mov-ref').value.trim();
    const reason    = document.getElementById('mov-reason').value.trim();
    const cost      = document.getElementById('mov-cost').value ? parseFloat(document.getElementById('mov-cost').value) : null;
    const initials  = document.getElementById('mov-initials').value.trim();
    const notes     = document.getElementById('mov-notes').value.trim();
    const msg       = document.getElementById('mov-msg');

    if (!productId || !type || !qty) {
      msg.style.display = ''; msg.style.color = 'var(--err)';
      msg.textContent = 'Product, type, and quantity are required.'; return;
    }
    msg.style.display = ''; msg.style.color = 'var(--text-soft)'; msg.textContent = 'Logging…';
    try {
      const res  = await fetch('/api/movements', {
        method: 'POST',
        headers: {'Content-Type':'application/json'},
        body: JSON.stringify({
          product_id: productId,
          movement_type: type,
          quantity: qty,
          movement_date: date || new Date().toISOString().slice(0,10),
          reference: ref || null,
          reason: reason || null,
          unit_cost_snapshot: cost,
          initials: initials || null,
          notes: notes || null,
        }),
      });
      const data = await res.json();
      if (data.id || data.ok) {
        msg.style.color = 'var(--accent)'; msg.textContent = '✓ Logged.';
        ['mov-qty','mov-ref','mov-reason','mov-cost','mov-initials','mov-notes'].forEach(id => {
          const el = document.getElementById(id); if (el) el.value = '';
        });
        document.getElementById('mov-type').value = 'production';
        movementsLoad();
        movPopulateProducts(); // refresh on-hand counts
      } else {
        msg.style.color = 'var(--err)'; msg.textContent = data.error || 'Error logging movement.';
      }
    } catch(e) {
      msg.style.color = 'var(--err)'; msg.textContent = 'Network error: ' + e.message;
    }
  }