// Stockyard Management — Stock Position · Register · Yard Transfers
// Enhanced: Movement Source Type · Auto-Rate Engine · Dynamic Entity Selection · Financial Calcs
const { useState: srSt, useEffect: srEf, useContext: srCtx, useMemo: srMemo } = React;
const AppCtx = window.AppCtx;
const SR_IN    = new Set(['Opening','Purchase','Transfer In','Adjustment In','Stock Transfer In','Customer Return']);
const SR_TYPES = ['Opening','Purchase','Customer Dispatch','Stock Transfer In','Stock Transfer Out','Customer Return','Adjustment In','Adjustment Out','Transfer In','Transfer Out','Sale'];

// ── resolveMovementType — SINGLE SOURCE OF TRUTH for inventory direction ─────
// Derives movement type from BOTH source AND destination. Never hardcodes Transfer In.
function resolveMovementType(mst, destType) {
  if (mst==='Stockyard'||mst==='Internal Stockyard') {
    if (destType==='Customer'||destType==='RMC Plant')            return 'Customer Dispatch';
    if (destType==='Stockyard'||destType==='Internal Stockyard') return 'Stock Transfer Out';
    if (destType==='Vendor')                                       return 'Vendor Return';
    return 'Customer Dispatch';
  }
  if (mst==='Vendor')    return 'Purchase';
  if (mst==='Crusher')   return 'Purchase';
  if (mst==='Customer')  return 'Customer Return';
  if (mst==='RMC Plant') return 'Sale';
  if (mst==='Debris')    return 'Adjustment In';
  return 'Adjustment In';
}

// ── resolveChallanNo — business-friendly challan identifier ──────────────────
function resolveChallanNo(m) {
  if (!m) return '—';
  if (m.type==='Opening')  return 'Opening Stock';
  if (m.reference)         return m.reference;
  if (m.challanNumber)     return m.challanNumber;
  if (m.poNumber && !/^Internal/i.test(m.poNumber)) return m.poNumber;
  return '—';
}

// ── Single shared source of truth for site entity types ─────────────────────
// Both Movement Source (Pickup) and Destination (Delivery) draw from this same list.
// This ensures the Transport Rate Master can always resolve a route from either side.
const SITE_ENTITY_TYPES = ['Vendor','Customer','Crusher','Stockyard','RMC Plant'];

// ── Movement Source Type — Pickup Site options ────────────────────────────
// Entity site types + operational-only entries (Debris, Manual Adjustment)
const MST_OPTIONS   = [...SITE_ENTITY_TYPES, 'Debris','Manual Adjustment'];
const MST_DOC_LABEL = {
  'Vendor':             'Purchase Challan',
  'Customer':           'Sales Return Challan',
  'Crusher':            'Crusher Slip',
  'Stockyard':          'Transfer Challan',
  'Internal Stockyard': 'Transfer Challan',   // legacy alias
  'RMC Plant':          'Plant Delivery Note',
  'Debris':             'Debris Ticket',
  'Manual Adjustment':  'Adjustment Note',
};
const MST_AUTO_TYPE = {
  'Vendor':             'Purchase',
  'Customer':           'Sale',
  'Crusher':            'Purchase',
  'Stockyard':          'Transfer In',
  'Internal Stockyard': 'Transfer In',        // legacy alias
  'RMC Plant':          'Sale',
  'Debris':             'Adjustment In',
};
const MST_ENTITY_LBL = {
  'Vendor':             'Vendor',
  'Customer':           'Customer',
  'Crusher':            'Crusher',
  'Stockyard':          'Source Stockyard',
  'Internal Stockyard': 'Source Stockyard',   // legacy alias
  'RMC Plant':          'RMC Plant',
};
const MST_NEEDS_ENTITY = new Set(['Vendor','Customer','Crusher','Stockyard','Internal Stockyard','RMC Plant']);
// Manual Adjustment uses manual rate; Debris is always zero-cost
const MST_MANUAL_RATE  = new Set(['Manual Adjustment']);
const MST_ZERO_RATE    = new Set(['Debris']);

// ── Destination Type — Delivery Site options ──────────────────────────────
// Exactly SITE_ENTITY_TYPES + 'Others' — same entity list as pickup, zero divergence.
const DEST_TYPES = [...SITE_ENTITY_TYPES, 'Others'];
const DEST_ENTITY_LBL = {
  'Vendor':             'Destination Vendor',
  'Customer':           'Destination Customer',
  'Crusher':            'Destination Crusher',
  'Stockyard':          'Destination Stockyard',
  'Internal Stockyard': 'Destination Stockyard', // legacy alias
  'RMC Plant':          'Destination RMC Plant',
};
function destGetEntities(destType, allStockyards, currentStockyardId) {
  if (destType==='Vendor')             return Store.all('vendors')  ||[];
  if (destType==='Customer')           return Store.all('customers')||[];
  if (destType==='Crusher')            return Store.all('crushers') ||[];
  if (destType==='Stockyard')          return (Store.all('stockyards')||[]).filter(s=>s.status==='Active'||!s.status);
  if (destType==='Internal Stockyard') return (Store.all('stockyards')||[]).filter(s=>s.id!==currentStockyardId&&(s.status==='Active'||!s.status));
  if (destType==='RMC Plant')          return Store.all('rmcPlants')||[];
  return [];
}

// ── Dynamic entity list — reads from master data, never hardcoded ─────────
function mstGetEntities(mst, stockyardId, stockyards) {
  if (mst==='Vendor')             return Store.all('vendors')  ||[];
  if (mst==='Customer')           return Store.all('customers')||[];
  if (mst==='Crusher')            return Store.all('crushers') ||[];
  // ── Issue 1 Fix: source dropdown reads from the full master list — never filtered by destination.
  // Both dropdowns derive from the same master; neither selection can corrupt the other's options.
  // Same-yard validation is enforced at save time only.
  if (mst==='Stockyard')          return (Store.all('stockyards')||[]).filter(s=>s.status==='Active'||!s.status);
  if (mst==='Internal Stockyard') return (Store.all('stockyards')||[]).filter(s=>s.status==='Active'||!s.status); // legacy alias
  if (mst==='RMC Plant')          return Store.all('rmcPlants')||[];
  return [];
}

// ── Material filter by source type — no hardcoded lists ──────────────────
function mstFilterMaterials(mst, entityId, allMaterials) {
  if (!mst) return allMaterials;
  // Vendor / Customer / RMC Plant → materials from their active Price Order
  if ((mst==='Vendor'||mst==='Customer'||mst==='RMC Plant') && entityId) {
    const pType = mst==='Vendor'?'vendor':'customer';
    const pos = (Store.data.priceOrders||[]).filter(po=>po.partyType===pType&&po.partyId===entityId&&po.isActive);
    const mids = new Set(pos.flatMap(po=>(po.rates||[]).map(r=>r.materialId)));
    if (mids.size>0) return (allMaterials||[]).filter(m=>mids.has(m.id));
  }
  // Crusher → materials listed in Crusher Master
  if (mst==='Crusher'&&entityId) {
    const cr = Store.byId('crushers',entityId);
    if (cr&&cr.materials) {
      const names = cr.materials.split(',').map(s=>s.trim().toLowerCase()).filter(Boolean);
      if (names.length>0) {
        const f=(allMaterials||[]).filter(m=>names.some(n=>m.name.toLowerCase().includes(n)));
        if (f.length>0) return f;
      }
    }
  }
  // Internal Stockyard → materials currently in stock at source yard
  if (mst==='Internal Stockyard'&&entityId) {
    const mids = new Set((Store.all('stockMovements')||[]).filter(m=>m.stockyardId===entityId).map(m=>m.materialId));
    if (mids.size>0) return (allMaterials||[]).filter(m=>mids.has(m.id));
  }
  // Debris → materials matching debris / soil / slag / dust
  if (mst==='Debris') {
    const f=(allMaterials||[]).filter(m=>/(debri|slag|soil|dust)/i.test(m.name));
    return f.length>0?f:allMaterials;
  }
  return allMaterials;
}

// ── Auto-rate: RateEngine (Price Orders) + internal avg ───────────────────
function mstFetchRate(mst, entityId, materialId, stockyardId, fallbackCoId) {
  if (!mst||!materialId) return null;
  const sy = Store.byId('stockyards',stockyardId)||{};
  const coId = sy.companyId||fallbackCoId;

  if (mst==='Vendor'&&entityId)
    return window.RateEngine.getPurchaseRate(coId,entityId,materialId);

  if ((mst==='Customer'||mst==='RMC Plant')&&entityId)
    return window.RateEngine.getSaleRate(coId,entityId,materialId);

  if (mst==='Crusher'&&entityId) {
    // Crusher → find matching vendor in Vendor Master for PO lookup
    const cr = Store.byId('crushers',entityId);
    if (cr) {
      const crN = cr.name.trim().toLowerCase();
      const vendors = Store.all('vendors')||[];
      let v = vendors.find(vv=>vv.name.trim().toLowerCase()===crN);
      if (!v) v = vendors.find(vv=>vv.name.trim().toLowerCase().includes(crN)||crN.includes(vv.name.trim().toLowerCase()));
      if (v) { const r=window.RateEngine.getPurchaseRate(coId,v.id,materialId); if(r) return r; }
    }
    return null;
  }

  if ((mst==='Internal Stockyard'||mst==='Stockyard')&&entityId) {
    // Weighted avg rate from source stockyard movements
    const movs=(Store.all('stockMovements')||[]).filter(
      m=>m.stockyardId===entityId&&m.materialId===materialId&&SR_IN.has(m.type)&&parseFloat(m.rate)>0
    );
    const totQ=movs.reduce((s,m)=>s+(parseFloat(m.quantity)||0),0);
    const totV=movs.reduce((s,m)=>s+(parseFloat(m.quantity)||0)*(parseFloat(m.rate)||0),0);
    if (totQ>0) return {rate:Math.round(totV/totQ),gst:'0',poNumber:'Internal Avg Rate'};
    return {rate:0,gst:'0',poNumber:'Internal Transfer'};
  }

  if (mst==='Debris')
    return {rate:0,gst:'0',poNumber:'Debris'};

  return null; // Manual Adjustment — manual rate entry
}

// ── Transport auto-rate from RateEngine (legacy PO-based) ───────────────
function mstFetchTrRate(transporterMasterId, materialId, stockyardId, fallbackCoId) {
  if (!transporterMasterId||!materialId) return null;
  const sy = Store.byId('stockyards',stockyardId)||{};
  const coId = sy.companyId||fallbackCoId;
  return window.RateEngine.getTransportRate(coId,transporterMasterId,materialId);
}

// ── Route-based Transport Rate — Pickup Entity → Destination Entity → Transporter → Material ──
// This is the ONLY source for transport rates. Never falls back to Price Orders or Purchase Orders.
// Priority: (1) exact match with transporter, (2) exact route match, (3) fuzzy route match.
function lookupRouteRate(pickupName, destName, materialName, transporterName, txnDate) {
  if (!pickupName || !destName || !materialName) return null;
  const norm = s => (s||'').trim().toLowerCase();
  const pN = norm(pickupName), dN = norm(destName), mN = norm(materialName);
  const tN = norm(transporterName||'');
  const TRR = window.TransportRateResolver;
  const onDate = TRR ? (TRR.dateOnly(txnDate) || TRR.todayBusiness()) : '';
  // Only rates effective on the MOVEMENT DATE are eligible — a future rate must
  // not activate early, and an expired rate must not resurface.
  const rates = (Store.all('transportRates')||[]).filter(r =>
    (r.status||'Active') !== 'Archived' && (!TRR || TRR.isEffectiveOn(r, onDate))
  );

  const routeMatch = r => {
    const rp = norm(r.crusherName||r.pickupName||'');
    const rd = norm(r.destinationName||r.customerName||'');
    const rm = norm(r.materialName||'');
    return rm === mN &&
      (rp === pN || pN.includes(rp) || rp.includes(pN)) &&
      (rd === dN || dN.includes(rd) || rd.includes(dN));
  };

  // 1. Exact match including transporter (highest priority when transporter is selected)
  if (tN) {
    const withTr = rates.find(r =>
      routeMatch(r) &&
      norm(r.transporterName||r.transporter||r.transporterId||'') === tN
    );
    if (withTr) return withTr;
  }
  // 2. Exact route match (pickup + destination + material, all normalised)
  const exact = rates.find(r =>
    norm(r.crusherName||r.pickupName||'') === pN &&
    norm(r.destinationName||r.customerName||'') === dN &&
    norm(r.materialName||'') === mN
  );
  if (exact) return exact;
  // 3. Fuzzy route match — partial name overlap
  return rates.find(routeMatch) || null;
}

// ── Yard Transfer: weighted avg rate from source yard ─────────────────────
function sourceYardAvgRate(stockyardId, materialId) {
  if (!stockyardId||!materialId) return 0;
  const movs=(Store.all('stockMovements')||[]).filter(
    m=>m.stockyardId===stockyardId&&m.materialId===materialId&&SR_IN.has(m.type)&&parseFloat(m.rate)>0
  );
  const totQ=movs.reduce((s,m)=>s+(parseFloat(m.quantity)||0),0);
  const totV=movs.reduce((s,m)=>s+(parseFloat(m.quantity)||0)*(parseFloat(m.rate)||0),0);
  return totQ>0?Math.round(totV/totQ):0;
}

// ── Financial Summary panel ───────────────────────────────────────────────
// netQty  = Customer Weighbridge / Challan qty  → used for Transport Cost
// invQty  = Inventory Deducted qty (after moisture adj) → used for Material Value
// qty     = legacy fallback when both are the same (no adjustment)
function SYFinSummary({ qty, netQty, invQty, matRate, trRate }) {
  const tq = parseFloat(netQty ?? qty)||0;  // transport qty — always net/challan
  const iq = parseFloat(invQty ?? qty)||0;  // inventory qty — gross after adjustment
  const mr=parseFloat(matRate)||0, tr=parseFloat(trRate)||0;
  const matVal=iq*mr, trCost=tq*tr, total=matVal+trCost;
  const q=tq||iq;
  if (!q) return null;
  return (
    <div style={{background:'#FFF7ED',border:'1px solid #FED7AA',borderRadius:6,padding:'10px 14px',marginTop:10}}>
      <div style={{fontWeight:700,fontSize:10.5,color:'var(--or)',marginBottom:8,textTransform:'uppercase',letterSpacing:'.05em'}}>
        Financial Summary — Live Calculation
      </div>
      <div className="dd-3col">
        {[
          ['Material Rate',  mr?window.fmtCur(mr):'—',           'var(--txt)'],
          ['Material Value', matVal?window.fmtCur(matVal):'—',   'var(--ok)'],
          ['Transport Rate', tr?window.fmtCur(tr):'—',           'var(--txt)'],
          ['Transport Cost', trCost?window.fmtCur(trCost):'—',   'var(--txt2)'],
          ['Total Cost',     total?window.fmtCur(total):'—',     'var(--or)'],
          ['Net Inv. Value', matVal?window.fmtCur(matVal):'—',   'var(--or)'],
        ].map(([l,v,c])=>(
          <div key={l}>
            <div style={{fontSize:9.5,color:'var(--txt3)',marginBottom:2,fontWeight:600,textTransform:'uppercase',letterSpacing:'.03em'}}>{l}</div>
            <div style={{fontWeight:700,fontSize:12,color:c,fontFamily:'var(--font)'}}>{v}</div>
          </div>
        ))}
      </div>
    </div>
  );
}

// ── Stock Position ─────────────────────────────────────────────────────────
function SYPosition({ stockyards, materials, onRefresh }) {
  // ── ROOT CAUSE FIX (v27) ─────────────────────────────────────────────────
  // PROBLEM: movements was received as a prop from StockyardPage. When the
  // Opening Stock modal closed (setShowOSModal → false), SYPosition re-rendered
  // immediately with the STALE prop — StockyardPage hadn't re-rendered yet
  // because useStoreSync has an 80ms debounce. Result: all KPIs and the table
  // showed zero / empty for ~80ms, which users perceived as "not propagating".
  //
  // FIX: Read movements directly from Store on every render. Any Store mutation
  // (opening stock save, movement add/edit/delete) is visible instantly at the
  // next re-render of this component — including the re-render triggered by
  // setShowOSModal(false) closing the modal. The 80ms debounce no longer
  // introduces a stale-data window because we bypass the prop chain entirely.
  // ─────────────────────────────────────────────────────────────────────────
  window.useStoreSync();
  const movements     = Store.all('stockMovements') || [];
  const openingStocks = Store.all('openingStocks')  || [];
  const { companyId } = srCtx(AppCtx);
  const isGroup   = companyId === 'group';
  const companies = Store.all('companies');

  const [selSY,      setSelSY]      = srSt('');
  const [search,     setSearch]     = srSt('');
  const [expKey,     setExpKey]     = srSt(null);
  const [showOSModal, setShowOSModal] = srSt(false);
  const [osDefaultSY, setOsDefaultSY] = srSt('');

  // ── Standardized Date Range Filter (shared DieselPeriodDropdown) ─────────
  const [periodPreset, setPeriodPreset] = srSt('all');
  const [customFrom,   setCustomFrom]   = srSt('');
  const [customTo,     setCustomTo]     = srSt('');
  const periodRange = srMemo(() => window.getDieselPeriodRange(periodPreset, customFrom, customTo), [periodPreset, customFrom, customTo]);
  const hasPeriod = !!(periodRange.from || periodRange.to);

  // Company-scoped stockyard list for the filter dropdown
  const scopedSY = srMemo(() => {
    const active = (stockyards || []).filter(s => s.status === 'Active' || !s.status);
    if (isGroup) return active;
    return active.filter(s => !s.companyId || s.companyId === companyId);
  }, [stockyards, companyId, isGroup]);

  // Summary bar — only when a specific stockyard is selected
  const summary = srMemo(() => {
    if (!selSY) return null;
    const tod  = new Date().toISOString().slice(0, 10);
    const syM  = movements.filter(m => m.stockyardId === selSY);
    // Primary: Opening entries in the inventory engine (stockMovements)
    const openQtyMov = syM.filter(m => m.type === 'Opening').reduce((s, m) => s + (parseFloat(m.quantity) || 0), 0);
    // Fallback: openingStocks table — used when stockMovements Opening entries
    // are missing (e.g. after a silent localStorage quota failure on a prior save)
    const openQtyRec = openingStocks.filter(r => r.stockyardId === selSY).reduce((s, r) => s + (r.qty || 0), 0);
    const openQty    = openQtyMov || openQtyRec;

    if (!hasPeriod) {
      const todM   = syM.filter(m => m.date === tod && m.type !== 'Opening');
      const todIn  = todM.filter(m =>  SR_IN.has(m.type)).reduce((s, m) => s + (parseFloat(m.quantity) || 0), 0);
      const todOut = todM.filter(m => !SR_IN.has(m.type)).reduce((s, m) => s + (parseFloat(m.quantity) || 0), 0);
      const allIn  = syM.filter(m =>  SR_IN.has(m.type)).reduce((s, m) => s + (parseFloat(m.quantity) || 0), 0);
      const allOut = syM.filter(m => !SR_IN.has(m.type)).reduce((s, m) => s + (parseFloat(m.quantity) || 0), 0);
      // When Opening movements are absent from stockMovements, supplement allIn
      const incWithFallback = openQtyMov > 0 ? allIn : allIn + openQtyRec;
      return { openQty, todIn, todOut, current: incWithFallback - allOut };
    }

    // Period-aware: Opening = balance carried forward as of the period start;
    // Stock In / Stock Out = movements dated within the selected range.
    const from = periodRange.from, to = periodRange.to;
    const nonOpenIn = syM.filter(m => SR_IN.has(m.type) && m.type !== 'Opening');
    const outAll    = syM.filter(m => !SR_IN.has(m.type));
    const priorIn   = from ? nonOpenIn.filter(m => m.date && m.date < from).reduce((s, m) => s + (parseFloat(m.quantity) || 0), 0) : 0;
    const priorOut  = from ? outAll.filter(m => m.date && m.date < from).reduce((s, m) => s + (parseFloat(m.quantity) || 0), 0) : 0;
    const periodIn  = nonOpenIn.filter(m => window.dieselInPeriod(m.date, from, to)).reduce((s, m) => s + (parseFloat(m.quantity) || 0), 0);
    const periodOut = outAll.filter(m => window.dieselInPeriod(m.date, from, to)).reduce((s, m) => s + (parseFloat(m.quantity) || 0), 0);
    const periodOpen = openQty + priorIn - priorOut;
    return { openQty: periodOpen, todIn: periodIn, todOut: periodOut, current: periodOpen + periodIn - periodOut };
  }, [movements, selSY, openingStocks, periodRange, hasPeriod]);

  // Centralized inventory calculation — Opening Stock + all inward/outward
  const rows = srMemo(() => {
    const syList = selSY
      ? (stockyards || []).filter(s => s.id === selSY)
      : scopedSY;
    const result = [];
    syList.forEach(sy => {
      // Build matId universe from BOTH stockMovements AND openingStocks so that
      // stockyards with only opening stock (no subsequent movements yet) still appear.
      const movMatIds  = new Set((movements || []).filter(m => m.stockyardId === sy.id).map(m => m.materialId));
      const openRecs   = (openingStocks || []).filter(r => r.stockyardId === sy.id);
      const openMatIds = new Set(openRecs.map(r => r.materialId).filter(Boolean));
      const matIds     = [...new Set([...movMatIds, ...openMatIds])];
      matIds.forEach(mid => {
        const mat = (materials || []).find(x => x.id === mid) || { name: mid, unit: 'MT', purchaseRate: 0 };
        const rel = (movements || []).filter(m => m.stockyardId === sy.id && m.materialId === mid);
        // Opening qty — primary from stockMovements, fallback from openingStocks table
        const openQtyMov = rel.filter(m => m.type === 'Opening').reduce((s, m) => s + (parseFloat(m.quantity) || 0), 0);
        const openQtyRec = openRecs.filter(r => r.materialId === mid).reduce((s, r) => s + (r.qty || 0), 0);
        const openQty    = openQtyMov || openQtyRec;
        let inc, out, cur, displayOpen;
        if (!hasPeriod) {
          const incFromMovs = rel.filter(m =>  SR_IN.has(m.type)).reduce((s, m) => s + (parseFloat(m.quantity) || 0), 0);
          // When Opening movements are missing from stockMovements, supplement inc
          // from openingStocks so Current Stock is never understated.
          inc  = openQtyMov > 0 ? incFromMovs : incFromMovs + openQtyRec;
          out  = rel.filter(m => !SR_IN.has(m.type)).reduce((s, m) => s + (parseFloat(m.quantity) || 0), 0);
          cur  = inc - out;
          displayOpen = openQty;
        } else {
          // Period-aware: Opening = balance carried forward as of the period start
          const from = periodRange.from, to = periodRange.to;
          const nonOpenIn = rel.filter(m => SR_IN.has(m.type) && m.type !== 'Opening');
          const outAll    = rel.filter(m => !SR_IN.has(m.type));
          const priorIn   = from ? nonOpenIn.filter(m => m.date && m.date < from).reduce((s, m) => s + (parseFloat(m.quantity) || 0), 0) : 0;
          const priorOut  = from ? outAll.filter(m => m.date && m.date < from).reduce((s, m) => s + (parseFloat(m.quantity) || 0), 0) : 0;
          inc = nonOpenIn.filter(m => window.dieselInPeriod(m.date, from, to)).reduce((s, m) => s + (parseFloat(m.quantity) || 0), 0);
          out = outAll.filter(m => window.dieselInPeriod(m.date, from, to)).reduce((s, m) => s + (parseFloat(m.quantity) || 0), 0);
          displayOpen = openQty + priorIn - priorOut;
          cur = displayOpen + inc - out;
        }
        if (cur <= 0 && displayOpen <= 0) return;
        const wtE  = rel.filter(m => SR_IN.has(m.type) && parseFloat(m.rate) > 0);
        const wtQ  = wtE.reduce((s, m) => s + (parseFloat(m.quantity) || 0), 0);
        const wtV  = wtE.reduce((s, m) => s + (parseFloat(m.quantity) || 0) * (parseFloat(m.rate) || 0), 0);
        const avg  = wtQ > 0 ? Math.round(wtV / wtQ) : (mat.purchaseRate || 0);
        const last = [...rel].sort((a, b) => (b.date || '').localeCompare(a.date || ''))[0];
        result.push({
          syId: sy.id, syName: sy.name, companyId: sy.companyId,
          materialId: mid, name: mat.name || mid, unit: mat.unit || 'MT',
          openQty: displayOpen, incoming: inc, outgoing: out, current: cur,
          avgRate: avg, value: Math.round(cur * avg), lastDate: last?.date || '',
        });
      });
    });
    if (!search) return result;
    const q = search.toLowerCase();
    return result.filter(r => r.name.toLowerCase().includes(q) || r.syName.toLowerCase().includes(q));
  }, [movements, stockyards, scopedSY, selSY, materials, search, openingStocks, periodRange, hasPeriod]);

  const ttl = srMemo(() => ({
    inc: rows.reduce((s, r) => s + r.incoming, 0),
    out: rows.reduce((s, r) => s + r.outgoing, 0),
    cur: rows.reduce((s, r) => s + r.current,  0),
    val: rows.reduce((s, r) => s + r.value,    0),
  }), [rows]);

  function exportCSV() {
    const h = isGroup
      ? 'Company,Stockyard,Material,Unit,Opening Stock,Incoming,Outgoing,Current Stock,Avg Rate,Stock Value'
      : 'Stockyard,Material,Unit,Opening Stock,Incoming,Outgoing,Current Stock,Avg Rate,Stock Value';
    const r = rows.map(r => {
      const co = isGroup ? `"${companies.find(c => c.id === r.companyId)?.name || ''}"` : null;
      const base = [`"${r.syName}"`,`"${r.name}"`,`"${r.unit}"`,r.openQty.toFixed(3),r.incoming.toFixed(3),r.outgoing.toFixed(3),r.current.toFixed(3),r.avgRate,r.value];
      return co ? [co, ...base].join(',') : base.join(',');
    }).join('\n');
    const b = new Blob([h + '\n' + r], { type: 'text/csv' });
    const a = document.createElement('a'); a.href = URL.createObjectURL(b);
    a.download = 'stock_position.csv'; a.click();
    window.toast && window.toast('CSV exported', 'ok');
  }

  function openOS(syId) {
    setOsDefaultSY(syId || selSY || '');
    setShowOSModal(true);
  }

  const togglePos = key => setExpKey(k => k === key ? null : key);
  const colSpanN  = isGroup ? 12 : 11;

  return (
    <div>
      {/* Page header */}
      <div className="ph" style={{ marginBottom: 10 }}>
        <div>
          <h1 style={{ fontSize: 15 }}>Stock Position</h1>
          <p style={{ fontSize: 11.5, color: 'var(--txt2)' }}>
            Current Stock = Opening Stock + All Inward − All Outward
            {isGroup && <span style={{ marginLeft: 8, color: 'var(--or)', fontWeight: 600 }}>· OM Group — All Companies</span>}
          </p>
        </div>
        <div className="ph-act">
          {/* Opening Stock button */}
          <button className="btn btn-wh btn-sm" onClick={() => openOS('')}
            style={{ borderColor: 'var(--or)', color: 'var(--or)' }}>
            <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
              <path d="M12 2L2 7l10 5 10-5-10-5z"/><path d="M2 17l10 5 10-5"/><path d="M2 12l10 5 10-5"/>
            </svg>
            Opening Stock
          </button>
          <button className="btn btn-wh btn-sm" onClick={exportCSV}>
            <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
              <path d="M21 15v4a2 2 0 01-2 2H5a2 2 0 01-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" y1="15" x2="12" y2="3"/>
            </svg>
            Export CSV
          </button>
        </div>
      </div>

      {/* Filter row */}
      <div className="frow">
        <window.FiltSelect placeholder={isGroup ? 'All Companies — All Stockyards' : 'All Active Stockyards'} value={selSY} onChange={v => setSelSY(v)} options={scopedSY.map(s => ({value:s.id,label:s.name+(isGroup ? ' — ' + (companies.find(c => c.id === s.companyId)?.name || '') : '')}))}/>
        <div className="fs">
          <svg className="fs-ic" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5"><circle cx="11" cy="11" r="8"/><path d="M21 21l-4.35-4.35"/></svg>
          <input value={search} onChange={e => setSearch(e.target.value)} placeholder="Search material or stockyard…" />
        </div>
        <window.DieselPeriodDropdown preset={periodPreset} onChange={setPeriodPreset} customFrom={customFrom} customTo={customTo} onCustomChange={(f,t)=>{ setCustomFrom(f); setCustomTo(t); }}/>
        <span className="f-cnt">{rows.length} records</span>
      </div>

      {/* Summary bar — shown when a specific yard is selected */}
      {summary && selSY && (
        <div className="dd-4col" style={{marginBottom:12}}>
          {[
            { lbl: hasPeriod ? 'Opening Stock (Period Start)' : 'Opening Stock', val: window.formatQuantity(summary.openQty) + ' MT',  clr: 'var(--info)',  ic: 'M12 2L2 7l10 5 10-5-10-5zM2 17l10 5 10-5M2 12l10 5 10-5' },
            { lbl: hasPeriod ? 'Stock In' : "Today's Stock In", val: window.formatQuantity(summary.todIn) + ' MT',    clr: 'var(--ok)',    ic: 'M12 5v14M5 12l7 7 7-7' },
            { lbl: hasPeriod ? 'Stock Out' : "Today's Stock Out",val: window.formatQuantity(summary.todOut) + ' MT',   clr: 'var(--err)',   ic: 'M12 19V5M5 12l7-7 7 7' },
            { lbl: 'Current Balance',  val: window.formatQuantity(summary.current) + ' MT',  clr: 'var(--or)',    ic: 'M3 3h18v18H3zM3 9h18M9 21V9' },
          ].map(({ lbl, val, clr, ic }) => (
            <div key={lbl} style={{ background: '#fff', border: '1px solid var(--bdr)', borderRadius: 10, padding: '10px 14px', borderTop: `3px solid ${clr}`, boxShadow: 'var(--sh-card)' }}>
              <div style={{ fontSize: 18, fontWeight: 800, color: clr, fontVariantNumeric: 'tabular-nums' }}>{val}</div>
              <div style={{ fontSize: 10.5, color: 'var(--txt2)', marginTop: 3, fontWeight: 600, textTransform: 'uppercase', letterSpacing: '.04em' }}>{lbl}</div>
            </div>
          ))}
        </div>
      )}

      {/* Stock table */}
      <div className="card">
        <div className="tbl-w">
          <table className="tbl">
            <thead>
              <tr>
                <th style={{ width: 28 }}></th>
                {isGroup && <th>COMPANY</th>}
                <th>STOCKYARD</th><th>MATERIAL</th><th>UNIT</th>
                <th>OPENING</th><th>STOCK IN</th><th>STOCK OUT</th><th>CURRENT STOCK</th>
                <th>AVG RATE</th><th>STOCK VALUE</th><th>LAST MOVEMENT</th>
              </tr>
            </thead>
            <tbody>
              {rows.length === 0 ? (
                <tr className="empty">
                  <td colSpan={colSpanN} style={{ textAlign: 'center', padding: 36, color: 'var(--txt2)' }}>
                    No stock data.{' '}
                    <span style={{ color: 'var(--or)', cursor: 'pointer', fontWeight: 600 }} onClick={() => openOS('')}>
                      Set Opening Stock →
                    </span>
                  </td>
                </tr>
              ) : rows.map(r => {
                const key = r.syId + ':' + r.materialId;
                const isExp = expKey === key;
                return (
                  <React.Fragment key={key}>
                    <tr onClick={() => togglePos(key)} style={{ cursor: 'pointer', background: isExp ? '#FFF7ED' : '' }}>
                      <td style={{ textAlign: 'center', padding: '0 8px' }}><window.SYChevron open={isExp} /></td>
                      {isGroup && (
                        <td style={{ fontSize: 11, color: 'var(--txt2)', whiteSpace: 'nowrap' }}>
                          {companies.find(c => c.id === r.companyId)?.name || '—'}
                        </td>
                      )}
                      <td style={{ fontWeight: 500 }}>{r.syName}</td>
                      <td><strong>{r.name}</strong></td>
                      <td style={{ color: 'var(--txt2)' }}>{r.unit}</td>
                      <td style={{ fontWeight: 600, color: 'var(--info)' }}>{r.openQty > 0 ? r.openQty.toFixed(3) : '—'}</td>
                      <td style={{ fontWeight: 600, color: 'var(--ok)' }}>{r.incoming.toFixed(3)}</td>
                      <td style={{ fontWeight: 600, color: 'var(--err)' }}>{r.outgoing.toFixed(3)}</td>
                      <td style={{ fontWeight: 700, color: 'var(--or)' }}>{r.current.toFixed(3)}</td>
                      <td>{window.fmtCur(r.avgRate)}</td>
                      <td style={{ fontWeight: 600 }}>{window.fmtCur(r.value)}</td>
                      <td style={{ color: 'var(--txt2)', fontSize: 11.5 }}>{r.lastDate ? window.fmtDate(r.lastDate) : '—'}</td>
                    </tr>
                    {isExp && (
                      <tr>
                        <td colSpan={colSpanN} style={{ padding: 0, borderBottom: '2px solid var(--or-bdr)' }}>
                          <window.SYPositionDrill row={r} movements={movements} materials={materials} />
                        </td>
                      </tr>
                    )}
                  </React.Fragment>
                );
              })}
            </tbody>
            {rows.length > 0 && (
              <tfoot>
                <tr>
                  <td style={{ background: '#F9FAFB', borderTop: '1px solid var(--bdr)' }}></td>
                  {isGroup && <td style={{ background: '#F9FAFB', borderTop: '1px solid var(--bdr)' }}></td>}
                  <td colSpan={3} style={{ fontWeight: 700, color: 'var(--txt2)', padding: '7px 10px', background: '#F9FAFB', borderTop: '1px solid var(--bdr)' }}>TOTALS</td>
                  <td style={{ fontWeight: 700, color: 'var(--info)', padding: '7px 10px', background: '#F9FAFB', borderTop: '1px solid var(--bdr)' }}>
                    {rows.reduce((s, r) => s + r.openQty, 0).toFixed(3)}
                  </td>
                  <td style={{ fontWeight: 700, color: 'var(--ok)', padding: '7px 10px', background: '#F9FAFB', borderTop: '1px solid var(--bdr)' }}>{ttl.inc.toFixed(3)}</td>
                  <td style={{ fontWeight: 700, color: 'var(--err)', padding: '7px 10px', background: '#F9FAFB', borderTop: '1px solid var(--bdr)' }}>{ttl.out.toFixed(3)}</td>
                  <td style={{ fontWeight: 700, color: 'var(--or)', padding: '7px 10px', background: '#F9FAFB', borderTop: '1px solid var(--bdr)' }}>{ttl.cur.toFixed(3)}</td>
                  <td style={{ padding: '7px 10px', background: '#F9FAFB', borderTop: '1px solid var(--bdr)' }}></td>
                  <td style={{ fontWeight: 700, color: 'var(--or)', padding: '7px 10px', background: '#F9FAFB', borderTop: '1px solid var(--bdr)' }}>{window.fmtCur(ttl.val)}</td>
                  <td style={{ padding: '7px 10px', background: '#F9FAFB', borderTop: '1px solid var(--bdr)' }}></td>
                </tr>
              </tfoot>
            )}
          </table>
        </div>
      </div>

      {/* Opening Stock Modal */}
      {showOSModal && (
        <window.OpeningStockModal
          stockyards={stockyards}
          materials={materials}
          defaultStockyardId={osDefaultSY}
          onClose={() => setShowOSModal(false)}
          onSaved={() => { onRefresh && onRefresh(); }}
        />
      )}
    </div>
  );
}
window.SYPosition = SYPosition;

// ── Stock Register ─────────────────────────────────────────────────────────
function SYRegister({ stockyards, materials, onRefresh }) {
  // Read movements directly from Store — same fix as SYPosition (v27).
  // Ensures Stock Register is always in sync without relying on parent prop timing.
  window.useStoreSync();
  const movements = Store.all('stockMovements') || [];
  const { session, companyId } = srCtx(AppCtx);
  const [modal,    setModal]    = srSt(false);
  const [form,     setForm]     = srSt({});
  const [autoRate, setAutoRate]   = srSt(null);   // { rate, gst, poNumber } | null
  const [autoTrR,  setAutoTrR]    = srSt(null);   // transport auto rate (PO-based, legacy)
  const [autoRouteTrR, setAutoRouteTrR] = srSt(null); // route-based transport rate from Transport Rate Master
  const [rateErr,  setRateErr]    = srSt('');
  const [routeErr, setRouteErr]   = srSt('');
  const [fSY,      setFSY]      = srSt('');
  const [fMat,     setFMat]     = srSt('');
  const [fType,    setFType]    = srSt('');
  const [dFrom,    setDFrom]    = srSt('');
  const [dTo,      setDTo]      = srSt('');
  const [pg,       setPg]       = srSt(1);
  const [expId,    setExpId]    = srSt(null);
  const [valDrill, setValDrill] = srSt(false);
  const [editMovId, setEditMovId] = srSt(null);
  const [delMovId,  setDelMovId]  = srSt(null);
  const [adjPct,        setAdjPct]        = srSt(0);    // active adjustment % (from Material Master or user override)
  const [adjEnabled,     setAdjEnabled]     = srSt(false); // user-toggled checkbox — OFF by default
  const [adjSectionOpen, setAdjSectionOpen] = srSt(false); // collapsible section
  const [adjType,        setAdjType]        = srSt('');    // selected adjustment type
  const [adjCustomType,  setAdjCustomType]  = srSt('');    // custom label when adjType='Other'
  const PER = 50;

  // Transporter Master integration
  const [syrTmAll,  setSyrTmAll]  = srSt(()=>Store.all('transporterMaster','group'));
  const [syrVehAll, setSyrVehAll] = srSt(()=>Store.all('vehicleMaster','group')||[]);
  srEf(()=>{const u=Store.on(()=>{setSyrTmAll(Store.all('transporterMaster','group'));setSyrVehAll(Store.all('vehicleMaster','group')||[]);});return u;},[]);
  const syrTmActive   = syrTmAll.filter(t=>t.status==='Active'||!t.status);
  const syrTmVehicles = srMemo(()=>form.transporterMasterId?syrVehAll.filter(v=>v.transporterId===form.transporterMasterId&&(v.status==='Active'||!v.status)):[],[syrVehAll,form.transporterMasterId]);

  // ── Dynamic entity list and material list (memo — no extra state needed)
  // form.stockyardId intentionally excluded from deps — source options no longer depend on destination selection.
  const dynEntities  = srMemo(()=>mstGetEntities(form.movementSourceType,form.stockyardId,stockyards),[form.movementSourceType,stockyards]);
  const dynMaterials    = srMemo(()=>mstFilterMaterials(form.movementSourceType,form.entityId,materials),[form.movementSourceType,form.entityId,materials]);
  // When destType=Stockyard and MST is also Stockyard, exclude the selected source yard (entityId)
  const dynDestEntities = srMemo(()=>{
    // For Stockyard MST the source yard is entityId, not stockyardId (field is hidden for those MSTs)
    const srcYardId = (form.movementSourceType==='Stockyard'||form.movementSourceType==='Internal Stockyard') ? form.entityId : form.stockyardId;
    const base = destGetEntities(form.destinationType,stockyards,srcYardId);
    if (form.destinationType==='Stockyard'&&form.entityId) return base.filter(s=>s.id!==form.entityId);
    return base;
  },[form.destinationType,stockyards,form.stockyardId,form.entityId,form.movementSourceType]);

  // matAdjConfig — reads Material Master defaults for pre-population; does NOT auto-enable adjustment
  const matAdjConfig = srMemo(()=>{
    if (!form.materialId) return null;
    const mat=(materials||[]).find(m=>m.id===form.materialId);
    if (!mat||!mat.qtyAdjEnabled||mat.qtyAdjStatus==='Inactive') return null;
    return mat;
  },[form.materialId,materials]);

  // adjTypeOptions — dynamic from Material Master; no hardcoded lists
  const adjTypeOptions = srMemo(()=>{
    const defaults=['Moisture','Dust Loss','Handling Loss','Shrinkage','Other'];
    if (!form.materialId) return defaults;
    const mat=(materials||[]).find(m=>m.id===form.materialId);
    if (!mat?.qtyAdjType||mat.qtyAdjType==='Other'||defaults.includes(mat.qtyAdjType)) return defaults;
    return [mat.qtyAdjType,...defaults];
  },[form.materialId,materials]);

  // ── Auto-rate: fires whenever source type / entity / material / stockyard change
  srEf(()=>{
    if (!modal) return;
    const r = mstFetchRate(form.movementSourceType,form.entityId,form.materialId,form.stockyardId,companyId);
    setAutoRate(r);
    const isManual = MST_MANUAL_RATE.has(form.movementSourceType);
    const isZero   = MST_ZERO_RATE.has(form.movementSourceType);
    const needsPO  = !isManual&&!isZero&&MST_NEEDS_ENTITY.has(form.movementSourceType);
    if (needsPO&&form.entityId&&form.materialId&&!r) {
      setRateErr('⚠ No active Price Order found for this combination. Create one in Price Orders module before saving.');
    } else {
      setRateErr('');
    }
  },[form.movementSourceType,form.entityId,form.materialId,form.stockyardId,modal,companyId]);

  // ── Transport auto-rate (PO-based, legacy fallback)
  srEf(()=>{
    if (!modal) return;
    setAutoTrR(mstFetchTrRate(form.transporterMasterId,form.materialId,form.stockyardId,companyId));
  },[form.transporterMasterId,form.materialId,form.stockyardId,modal,companyId]);

  // ── Route-based Transport Rate — Transport Rate Master lookup ──────────
  // Lookup key: Pickup Entity → Destination Entity → Transporter → Material
  // This is the sole source of transport rates. PO/Purchase Order rates are never used here.
  srEf(()=>{
    if (!modal) { setAutoRouteTrR(null); setRouteErr(''); return; }
    const pickup       = form.entityName||'';
    const dest         = form.destinationName||'';
    const transporter  = form.transporterName||'';
    const mat          = (materials||[]).find(m=>m.id===form.materialId);
    const matName      = mat?.name||'';
    if (!pickup||!dest||!matName) { setAutoRouteTrR(null); setRouteErr(''); return; }
    const rate = lookupRouteRate(pickup, dest, matName, transporter, form.date);
    setAutoRouteTrR(rate||null);
    if (!rate) {
      const trHint = transporter ? ` via ${transporter}` : '';
      setRouteErr('No Transport Rate effective on '+(form.date||'this date')+' for: '+pickup+' → '+dest+trHint+' ('+matName+'). Add or extend it in Transport Rate Master.');
    } else {
      setRouteErr('');
    }
  },[form.entityName, form.destinationName, form.materialId, form.destinationType, form.transporterName, form.date, modal]);

  const filtered = srMemo(() => {
    return [...(movements||[])].sort((a,b)=>(b.date||'').localeCompare(a.date||'')).filter(m => {
      if (fSY   && m.stockyardId !== fSY)   return false;
      if (fMat  && m.materialId  !== fMat)  return false;
      if (fType && m.type        !== fType) return false;
      if (dFrom && m.date < dFrom)          return false;
      if (dTo   && m.date > dTo)            return false;
      return true;
    });
  }, [movements, fSY, fMat, fType, dFrom, dTo]);

  const totals = srMemo(()=>{
    const inR  = filtered.filter(m=>SR_IN.has(m.type));
    const outR = filtered.filter(m=>!SR_IN.has(m.type));
    return {
      inQty:  inR.reduce((s,m)=>s+(parseFloat(m.quantity)||0),0),
      outQty: outR.reduce((s,m)=>s+(parseFloat(m.quantity)||0),0),
      inVal:  inR.reduce((s,m)=>s+(parseFloat(m.value)||0),0),
      outVal: outR.reduce((s,m)=>s+(parseFloat(m.value)||0),0),
    };
  },[filtered]);

  const totalPgs = Math.ceil(filtered.length/PER);
  const paged    = filtered.slice((pg-1)*PER, pg*PER);

  const setF = (k,v) => setForm(p=>({...p,[k]:v}));
  const clr  = ()=>{setFSY('');setFMat('');setFType('');setDFrom('');setDTo('');setPg(1);};
  const toggleReg = id => setExpId(v=>v===id?null:id);
  const netVal = totals.inVal - totals.outVal;
  const netQty = totals.inQty - totals.outQty;

  // ── MST cascade handlers (reset downstream fields on change)
  function changeMST(val) {
    // Auto-set destinationType to Stockyard for yard-to-yard transfers so the receiving yard field appears immediately
    const autoDestType = (val==='Stockyard'||val==='Internal Stockyard') ? 'Stockyard' : '';
    setForm(p=>({...p,
      movementSourceType:val, entityId:'', entityName:'', materialId:'',
      adjustType:'Adjustment In', manualRate:'',
      destinationType:autoDestType, destinationId:'', destinationName:'',
      stockyardId: p.stockyardId,
    }));
    setAutoRate(null); setAutoTrR(null); setAutoRouteTrR(null); setRateErr(''); setRouteErr('');
    setAdjEnabled(false); setAdjSectionOpen(false); setAdjType(''); setAdjCustomType(''); setAdjPct(0);
  }
  function changeEntity(id) {
    const ent = dynEntities.find(e=>e.id===id);
    setForm(p=>{
      const isYardDest = p.destinationType==='Stockyard'||p.destinationType==='Internal Stockyard';
      return {...p,
        entityId:id, entityName:ent?.name||'', materialId:'',
        // If the destination entity was the same yard now selected as source, clear it
        // so the destination select never silently holds a value absent from its option list.
        destinationId:   isYardDest && p.destinationId===id ? '' : p.destinationId,
        destinationName: isYardDest && p.destinationId===id ? '' : p.destinationName,
      };
    });
    setAutoRate(null); setRateErr('');
  }
  function changeMaterial(id) {
    const _mat=(materials||[]).find(m=>m.id===id);
    const hasAdj=(_mat?.qtyAdjEnabled&&_mat?.qtyAdjStatus!=='Inactive');
    setAdjPct(hasAdj?(parseFloat(_mat.qtyAdjPct)||0):0);
    setAdjType(hasAdj?(_mat.qtyAdjType||'Moisture'):'');
    setAdjCustomType('');
    if (hasAdj) setAdjSectionOpen(true); // expand so user sees defaults
    setAdjEnabled(false); // always reset: optional, OFF by default
    setForm(p=>({...p,materialId:id}));
    setAutoRate(null);setRateErr('');
  }
  function changeTransporter(id) {
    const tm = syrTmActive.find(t=>t.id===id);
    setForm(p=>({...p, transporterMasterId:id, transporterName:tm?.name||'', vehicleFull:''}));
    setAutoTrR(null);
  }
  function changeDestType(val) {
    setForm(p=>({...p, destinationType:val, destinationId:'', destinationName:''}));
    setAutoRouteTrR(null); setRouteErr('');
  }
  function changeDestination(id) {
    const ent = dynDestEntities.find(e=>e.id===id);
    setForm(p=>({...p, destinationId:id, destinationName:ent?.name||''}));
    setAutoRouteTrR(null); setRouteErr('');
  }

  function openAdd() {
    setEditMovId(null);
    setForm({
      date: new Date().toISOString().slice(0,10),
      stockyardId: '', movementSourceType: '',
      entityId: '', entityName: '',
      materialId: '', adjustType: 'Adjustment In',
      quantity: '', manualRate: '',
      documentNumber: '', notes: '',
      transporterMasterId: '', transporterName: '', vehicleFull: '',
      destinationType: '', destinationId: '', destinationName: '',
    });
    setAutoRate(null); setAutoTrR(null); setAutoRouteTrR(null); setRateErr(''); setRouteErr('');
    setAdjPct(0); setAdjEnabled(false); setAdjSectionOpen(false); setAdjType(''); setAdjCustomType('');
    setModal(true);
  }

  function openEditMov(m) {
    setEditMovId(m.id);
    const isManual = MST_MANUAL_RATE.has(m.movementSourceType);
    const adjOn = !!m.adjustmentEnabled;
    const netQ  = parseFloat(m.netQuantity != null ? m.netQuantity : m.quantity) || 0;
    // Backward compat: old Stockyard/InternalStockyard transfers stored receiving yard in stockyardId.
    // Map it into destinationId so the refactored form displays it correctly without data loss.
    const _isOldYardXfer = (m.movementSourceType==='Stockyard'||m.movementSourceType==='Internal Stockyard') && m.stockyardId && !m.destinationId;
    const _destType = _isOldYardXfer ? 'Stockyard'                                      : (m.destinationType||'');
    const _destId   = _isOldYardXfer ? m.stockyardId                                    : (m.destinationId||'');
    const _destName = _isOldYardXfer ? (Store.name('stockyards',m.stockyardId)||'')     : (m.destinationName||'');
    setForm({
      date:                m.date||new Date().toISOString().slice(0,10),
      stockyardId:         m.stockyardId||'',
      movementSourceType:  m.movementSourceType||'',
      entityId:            m.entityId||'',
      entityName:          m.entityName||'',
      materialId:          m.materialId||'',
      adjustType:          isManual ? (m.type||'Adjustment In') : 'Adjustment In',
      quantity:            String(netQ),
      manualRate:          isManual ? String(m.rate||'') : '',
      documentNumber:      m.reference||'',
      notes:               m.notes||'',
      transporterMasterId: m.transporterMasterId||'',
      transporterName:     m.transporterName||'',
      vehicleFull:         m.vehicleFull||'',
      destinationType:     _destType,
      destinationId:       _destId,
      destinationName:     _destName,
    });
    setAdjEnabled(adjOn);
    setAdjPct(adjOn ? (parseFloat(m.adjustmentPct)||0) : 0);
    setAdjType(adjOn ? (m.adjustmentType||'') : '');
    setAdjCustomType('');
    setAdjSectionOpen(adjOn);
    setAutoRate(null); setAutoTrR(null); setAutoRouteTrR(null); setRateErr(''); setRouteErr('');
    setModal(true);
  }

  function handleSave(e) {
    e.preventDefault();
    const mst = form.movementSourceType;
    if (!mst) { window.toast&&window.toast('Select a Movement Source Type','er'); return; }
    if (MST_NEEDS_ENTITY.has(mst)&&!form.entityId) {
      window.toast&&window.toast(`Select a ${MST_ENTITY_LBL[mst]||'Entity'}`, 'er'); return;
    }
    // For Stockyard/InternalStockyard transfers: effectiveSyId = Destination Stockyard (destinationId).
    // The standalone Stockyard field is hidden for these MSTs — destination yard is set via the Destination section.
    // For all other MSTs: effectiveSyId = Source Stockyard (stockyardId).
    const isYardMST = mst==='Stockyard'||mst==='Internal Stockyard';
    // ── Destination validation: driven by the SELECTED destinationType, not by MST ──
    // Stockyard MST supports multiple destination types: Stockyard (yard transfer),
    // Customer (dispatch), Internal Stockyard, RMC Plant, etc.
    // Do NOT restrict destination type based on MST alone.
    const isYardDestination = form.destinationType==='Stockyard'||form.destinationType==='Internal Stockyard';
    // effectiveSyId = the stockyard whose inventory is affected:
    //   • Yard→Yard transfer: receiving yard (destinationId) receives stock
    //   • Yard→Customer/other: source yard (entityId) loses stock
    //   • Non-yard MST: source stockyard field (stockyardId)
    // Source yard always owns the inventory event; Yard→Yard gets a second inbound record below
    const effectiveSyId = isYardMST ? form.entityId : form.stockyardId;
    if (!effectiveSyId) {
      window.toast&&window.toast('Select a Source Stockyard','er'); return;
    }
    // Same-yard check: only applies when both source and destination are stockyards
    if (isYardMST&&isYardDestination&&form.entityId&&form.entityId===form.destinationId) {
      window.toast&&window.toast('Source and Destination Stockyard cannot be the same','er'); return;
    }
    if (!form.materialId) { window.toast&&window.toast('Select a Material','er'); return; }
    // ── Quantity Adjustment Engine (save) — dynamic, no hardcoded material names or percentages ──
    const _netQtySv = parseFloat(form.quantity)||0;
    if (!_netQtySv||_netQtySv<=0) { window.toast&&window.toast('Enter a valid quantity','er'); return; }
    // Adjustment driven by user toggle — snapshotted at save time
    const _adjPctSv   = adjEnabled ? adjPct : 0;
    const _adjTypeSv  = adjEnabled ? (adjType==='Other'?(adjCustomType||'Other'):adjType) : '';
    const _grossQtySv = adjEnabled && _adjPctSv<100
      ? _netQtySv / (1 - _adjPctSv/100)
      : _netQtySv;
    const _invDedSv  = _grossQtySv;
    const q = _invDedSv;

    const isManual = MST_MANUAL_RATE.has(mst);
    const isZero   = MST_ZERO_RATE.has(mst);
    const isYardTransfer = (mst==='Stockyard'||mst==='Internal Stockyard');
    const needsPO  = !isManual&&!isZero&&!isYardTransfer&&MST_NEEDS_ENTITY.has(mst);
    if (needsPO&&!autoRate) {
      window.toast&&window.toast('No applicable Price Order found. Please create a Price Order for this party and material before saving.','er');
      return;
    }

    const r   = isManual ? (parseFloat(form.manualRate)||0) : (autoRate?.rate||0);
    const val = q * r;
    const mvType = isManual ? (form.adjustType||'Adjustment In') : resolveMovementType(mst, form.destinationType);
    const coId = (Store.byId('stockyards',effectiveSyId)||{}).companyId||'';

    const mvData = {
      date:           form.date,
      stockyardId:    effectiveSyId,
      materialId:     form.materialId,
      type:           mvType,
      quantity:       q,
      netQuantity:    adjEnabled ? _netQtySv : q,
      adjustmentEnabled: adjEnabled,
      adjustmentPct:  _adjPctSv,
      adjustmentType: _adjTypeSv,
      grossQuantity:  _grossQtySv,
      inventoryDeduction: _invDedSv,
      rate:           r,
      value:          val,
      movementSourceType: mst,
      entityId:       form.entityId||'',
      entityName:     form.entityName||'',
      poNumber:       autoRate?.poNumber||'',
      reference:      form.documentNumber||'',
      challanNumber:  form.documentNumber||'',
      pickupPoint:    form.entityName||Store.name('stockyards',form.stockyardId)||'',
      destination:    form.destinationName||'',
      notes:          form.notes||'',
      transporterMasterId: form.transporterMasterId||'',
      transporterName:form.transporterName||'',
      vehicleFull:    form.vehicleFull||'',
      destinationType:form.destinationType||'',
      destinationId:  form.destinationId||'',
      destinationName:form.destinationName||'',
      transportRate:  autoRouteTrR?.ratePerTon||0,
      // Transport cost always uses net quantity (customer weighbridge), never inventory deducted qty
      transportCost:  _netQtySv * (autoRouteTrR?.ratePerTon||0),
      companyId:      coId,
    };
    let savedId;
    if (editMovId) {
      Store.update('stockMovements', editMovId, {...mvData, updatedBy:session?.userName||'System', lastUpdated:new Date().toISOString().slice(0,10)});
      savedId = editMovId;
      Store.addLog('UPDATE','Stock Movement',`Updated ${mvType}: ${q}T ${Store.name('materials',form.materialId)} @ ${Store.name('stockyards',effectiveSyId)}`);
      (Store.all('transportEntries')||[]).filter(e=>e._stockMovementId===editMovId).forEach(e=>Store.del('transportEntries',e.id));
    } else {
      const mv = Store.add('stockMovements',{...mvData, createdBy:session?.userName||'System'});
      savedId = mv?.id||'';
      Store.addLog('CREATE','Stock Movement',`${mvType}: ${q}T ${Store.name('materials',form.materialId)} @ ${Store.name('stockyards',effectiveSyId)} [${mst}]`);
      // Yard→Yard: create inbound movement at destination yard
      if (isYardMST&&isYardDestination&&form.destinationId&&form.destinationId!==form.entityId) {
        const destCoId=(Store.byId('stockyards',form.destinationId)||{}).companyId||'';
        Store.add('stockMovements',{...mvData,type:'Stock Transfer In',stockyardId:form.destinationId,companyId:destCoId,
          pickupPoint:form.entityName||'',destination:Store.name('stockyards',form.destinationId)||form.destinationName||'',
          destinationType:'Stockyard',destinationId:form.destinationId,destinationName:Store.name('stockyards',form.destinationId)||form.destinationName||'',
          createdBy:session?.userName||'System',_linkedTransferOutId:savedId});
      }
    }
    const _showTransport = mvType !== 'Sale' && mvType !== 'Customer Dispatch';
    if (_showTransport && form.transporterMasterId&&form.vehicleFull) {
      Store.add('transportEntries',{
        date:form.date, companyId:coId,
        transporterId:form.transporterMasterId, transporter:form.transporterName||'',
        vehicleFull:form.vehicleFull, materialId:form.materialId,
        material:Store.name('materials',form.materialId),
        quantity:adjEnabled ? _netQtySv : q, unit:(Store.byId('materials',form.materialId)||{}).unit||'MT',
        status:'Delivered', source:'Auto Generated', sourceModule:'STOCKYARD',
        _transportQuantitySource:adjEnabled ? 'Net Quantity (Adj)' : 'Net Quantity',
        _autoGenerated:true, _stockMovementType:mvType,
        _stockMovementId:savedId,
        _stockyardId:effectiveSyId, _stockyardName:Store.name('stockyards',effectiveSyId),
        _destinationType:form.destinationType||'', _destinationId:form.destinationId||'', _destinationName:form.destinationName||'',
        _pickupName:form.entityName||Store.name('stockyards',effectiveSyId)||'',
        ratePerTon:autoRouteTrR?.ratePerTon||0,
        amount:(adjEnabled?_netQtySv:q)*(autoRouteTrR?.ratePerTon||0),
        reference:form.documentNumber||'', challanNumber:'',
        createdBy:session?.userName||'System',
        _creationTimestamp:new Date().toISOString(),
        lastUpdated:new Date().toISOString().slice(0,10),
      });
    }
    setModal(false); setEditMovId(null); onRefresh();
    window.toast&&window.toast(editMovId?'Movement updated':'Movement recorded','ok');
  }

  function handleDeleteMov() {
    (Store.all('transportEntries')||[]).filter(e=>e._stockMovementId===delMovId).forEach(e=>Store.del('transportEntries',e.id));
    Store.del('stockMovements', delMovId);
    Store.addLog('DELETE','Stock Movement','Deleted by '+(session?.userName||'System'));
    setDelMovId(null); onRefresh();
    window.toast&&window.toast('Stock movement deleted','ok');
  }

  function exportCSV() {
    const h='Date,Stockyard,Material,Type,Pickup Point,Destination,Quantity,Rate,Value,Challan No.';
    const r=filtered.map(m=>`"${m.date}","${Store.name('stockyards',m.stockyardId)}","${Store.name('materials',m.materialId)}","${m.type}","${m.pickupPoint||m.entityName||''}","${m.destination||m.destinationName||''}","${m.quantity}","${m.rate||0}","${m.value||0}","${resolveChallanNo(m)}"`).join('\n');
    const b=new Blob([h+'\n'+r],{type:'text/csv'});const a=document.createElement('a');a.href=URL.createObjectURL(b);a.download='stock_register.csv';a.click();
    window.toast&&window.toast('CSV exported','ok');
  }

  // Render-time derived quantities
  const _netQtyR   = parseFloat(form.quantity)||0;
  const _adjPctR   = adjEnabled ? adjPct : 0;
  const _grossQtyR = adjEnabled && _adjPctR<100 ? _netQtyR / (1 - _adjPctR/100) : _netQtyR;
  const _invDedR   = _grossQtyR;

  const isManualMST   = MST_MANUAL_RATE.has(form.movementSourceType);
  // Hide transport for Sale movements (already created by Sales Order)
  const _mvTypeForTr  = isManualMST ? (form.adjustType||'Adjustment In') : resolveMovementType(form.movementSourceType, form.destinationType);
  const showTransport = !!form.movementSourceType && !['Sale','Customer Dispatch'].includes(_mvTypeForTr);
  const docLabel    = MST_DOC_LABEL[form.movementSourceType]||'Reference Number';
  const rateDisplay = isManualMST
    ? null
    : autoRate
      ? `₹${Number(autoRate.rate).toLocaleString('en-IN')} — ${autoRate.poNumber||'PO'}`
      : (form.entityId&&form.materialId ? 'No Price Order' : '—');

  return (
    <div>
      <div className="ph" style={{marginBottom:10}}>
        <div><h1 style={{fontSize:15}}>Stock Register</h1><p style={{fontSize:11.5,color:'var(--txt2)'}}>Complete movement history — click any row to drill down</p></div>
        <div className="ph-act">
          <button className="btn btn-wh btn-sm" onClick={exportCSV}><svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M21 15v4a2 2 0 01-2 2H5a2 2 0 01-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" y1="15" x2="12" y2="3"/></svg> Export CSV</button>
          <button className="btn btn-or" onClick={openAdd}><svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg> Add Movement</button>
        </div>
      </div>
      <div className="fp" style={{marginBottom:8}}>
        <div className="fp-row">
          <div className="fp-fld"><label>Start Date</label><input type="date" value={dFrom} onChange={e=>setDFrom(e.target.value)}/></div>
          <div className="fp-fld"><label>End Date</label><input type="date" value={dTo} onChange={e=>setDTo(e.target.value)}/></div>
          <div className="fp-fld"><label>Stockyard</label>
            <select value={fSY} onChange={e=>{setFSY(e.target.value);setPg(1);}}>
              <option value="">All</option>{stockyards.map(s=><option key={s.id} value={s.id}>{s.name}</option>)}
            </select>
          </div>
          <div className="fp-fld"><label>Material</label>
            <select value={fMat} onChange={e=>{setFMat(e.target.value);setPg(1);}}>
              <option value="">All</option>{materials.map(m=><option key={m.id} value={m.id}>{m.name}</option>)}
            </select>
          </div>
          <div className="fp-fld"><label>Type</label>
            <select value={fType} onChange={e=>{setFType(e.target.value);setPg(1);}}>
              <option value="">All Types</option>{SR_TYPES.map(t=><option key={t} value={t}>{t}</option>)}
            </select>
          </div>
          <div className="fp-acts"><button className="btn btn-gh btn-sm" onClick={clr}>Clear All</button></div>
        </div>
      </div>
      <div className="frow" style={{marginBottom:8}}><span className="f-cnt">{filtered.length} records</span></div>

      <div className="card">
        <div className="tbl-w">
          <table className="tbl">
            <thead><tr>
              <th style={{width:28}}></th>
              <th>DATE</th><th>STOCKYARD</th><th>MATERIAL</th><th>TYPE</th>
              <th>QUANTITY</th><th>UNIT</th><th>PICKUP POINT</th><th>DESTINATION</th><th>RATE</th><th>VALUE</th><th>CHALLAN NO.</th><th>CREATED BY</th><th>ACTIONS</th>
            </tr></thead>
            <tbody>
              {paged.length===0
                ? <tr className="empty"><td colSpan="14" style={{textAlign:'center',padding:36,color:'var(--txt2)'}}>No movements for selected filters.</td></tr>
                : paged.map(m=>{
                  const isIn=SR_IN.has(m.type); const mat=(materials||[]).find(x=>x.id===m.materialId)||{unit:'MT'}; const isExp=expId===m.id;
                  const pickupDisp=m.pickupPoint||m.entityName||''; const destDisp=m.destination||m.destinationName||'';
                  return (
                    <React.Fragment key={m.id}>
                      <tr onClick={()=>toggleReg(m.id)} style={{cursor:'pointer',background:isExp?'#FFF7ED':''}}>
                        <td style={{textAlign:'center',padding:'0 8px'}}><window.SYChevron open={isExp}/></td>
                        <td style={{whiteSpace:'nowrap'}}>{window.fmtDate(m.date)}</td>
                        <td style={{fontWeight:500}}>{(stockyards||[]).find(s=>s.id===m.stockyardId)?.name||'—'}</td>
                        <td>{Store.name('materials',m.materialId)}</td>
                        <td><span className={`bdg ${isIn?'bg-gn':'bg-rd'}`}>{m.type}</span></td>
                        <td style={{fontWeight:600,color:isIn?'var(--ok)':'var(--err)',fontFamily:'var(--font)'}}>
                          {isIn?'+':'-'}{Number(m.quantity||0).toFixed(3)}
                          {(m.adjustmentPct>0)&&(
                            <div style={{fontSize:9.5,color:'var(--txt3)',fontWeight:400,lineHeight:1.2}}>
                              Net: {Number(m.netQuantity||m.quantity).toFixed(3)} · {m.adjustmentType||'Adj'} {m.adjustmentPct}%
                            </div>
                          )}
                        </td>
                        <td style={{color:'var(--txt2)'}}>{mat.unit||'MT'}</td>
                        <td style={{fontSize:11.5,maxWidth:120,overflow:'hidden',textOverflow:'ellipsis',whiteSpace:'nowrap'}}>{pickupDisp||'—'}</td>
                        <td style={{fontSize:11.5,maxWidth:120,overflow:'hidden',textOverflow:'ellipsis',whiteSpace:'nowrap'}}>{destDisp||'—'}</td>
                        <td>{m.rate?window.fmtCur(m.rate):'—'}</td>
                        <td style={{fontWeight:600}}>{m.value?window.fmtCur(m.value):'—'}</td>
                        <td style={{fontSize:11,fontFamily:'var(--font)',color:'var(--txt2)'}}>{resolveChallanNo(m)}</td>
                        <td style={{fontSize:11.5,color:'var(--txt2)'}}>{m.createdBy||'—'}</td>
                        <td onClick={e=>e.stopPropagation()}>
                          <div className="ra">
                            <button className="btn btn-wh btn-sm" onClick={()=>openEditMov(m)}>Edit</button>
                            <button className="btn btn-rd btn-sm" onClick={()=>setDelMovId(m.id)}>Delete</button>
                          </div>
                        </td>
                      </tr>
                      {isExp&&(
                        <tr><td colSpan={14} style={{padding:0,borderBottom:'2px solid var(--or-bdr)'}}>
                          <window.SYRegisterDrill m={m} movements={movements} materials={materials}/>
                        </td></tr>
                      )}
                    </React.Fragment>
                  );
                })}
            </tbody>
            {filtered.length>0&&(
              <tfoot>
                <tr style={{background:'#FFF7ED'}}>
                  <td style={{borderTop:'2px solid var(--or-bdr)'}}></td>
                  <td colSpan={3} style={{fontWeight:700,fontSize:11.5,color:'var(--txt2)',padding:'8px 10px',borderTop:'2px solid var(--or-bdr)'}}>REGISTER TOTALS — {filtered.length} records</td>
                  <td style={{padding:'8px 10px',borderTop:'2px solid var(--or-bdr)'}}>
                    <div style={{fontSize:10,color:'var(--txt3)',marginBottom:2,fontWeight:600,textTransform:'uppercase',letterSpacing:'.03em'}}>Direction</div>
                    <div style={{fontSize:11,color:'var(--ok)',fontWeight:700}}>↓ Inward</div>
                    <div style={{fontSize:11,color:'var(--err)',fontWeight:700}}>↑ Outward</div>
                  </td>
                  <td style={{padding:'8px 10px',borderTop:'2px solid var(--or-bdr)',fontFamily:'var(--font)'}}>
                    <div style={{fontSize:10,color:'var(--txt3)',marginBottom:2,fontWeight:600,textTransform:'uppercase',letterSpacing:'.03em'}}>Quantity</div>
                    <div style={{color:'var(--ok)',fontWeight:700}}>+{totals.inQty.toFixed(3)}</div>
                    <div style={{color:'var(--err)',fontWeight:700}}>-{totals.outQty.toFixed(3)}</div>
                  </td>
                  <td colSpan={4} style={{padding:'8px 10px',borderTop:'2px solid var(--or-bdr)'}}>
                    <div style={{fontSize:10,color:'var(--txt3)',marginBottom:2,fontWeight:600,textTransform:'uppercase',letterSpacing:'.03em'}}>Net Stock</div>
                    <div style={{fontWeight:700,color:'var(--or)',fontFamily:'var(--font)',fontSize:12}}>{netQty.toFixed(3)} T</div>
                  </td>
                  <td style={{padding:'8px 10px',borderTop:'2px solid var(--or-bdr)'}}>
                    <div style={{fontSize:10,color:'var(--txt3)',marginBottom:3,fontWeight:600,textTransform:'uppercase',letterSpacing:'.03em'}}>Net Inventory Value</div>
                    <button onClick={()=>setValDrill(true)} style={{fontWeight:700,fontSize:13,color:'var(--or)',background:'none',border:'none',cursor:'pointer',fontFamily:'var(--font)',display:'flex',alignItems:'center',gap:4,padding:0,textDecoration:'underline dotted'}} title="Click to drill down into value composition">
                      {window.fmtCur(netVal)}
                      <svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5"><circle cx="11" cy="11" r="8"/><path d="M21 21l-4.35-4.35"/></svg>
                    </button>
                  </td>
                  <td colSpan={3} style={{padding:'8px 10px',borderTop:'2px solid var(--or-bdr)'}}></td>
                </tr>
              </tfoot>
            )}
          </table>
        </div>
      </div>

      {totalPgs>1&&<div className="pag"><button className="pg-b" onClick={()=>setPg(1)} disabled={pg===1}>«</button><button className="pg-b" onClick={()=>setPg(p=>p-1)} disabled={pg===1}>‹</button><span className="pg-inf">Page {pg} of {totalPgs}</span><button className="pg-b" onClick={()=>setPg(p=>p+1)} disabled={pg===totalPgs}>›</button><button className="pg-b" onClick={()=>setPg(totalPgs)} disabled={pg===totalPgs}>»</button></div>}

      {valDrill&&<window.SYValueDrillModal rows={filtered} materials={materials} stockyards={stockyards} onClose={()=>setValDrill(false)}/>}
      {delMovId&&<window.Confirm onOk={handleDeleteMov} onCancel={()=>setDelMovId(null)}/>}

      {/* ── Add Movement Modal ── */}
      {modal&&(
        <div className="mbg">
          <div className="mod mod-lg">
            <div className="mod-hd">
              <h2>{editMovId?'Edit':'Add'} Stock Movement</h2>
              <button className="mod-x" onClick={()=>setModal(false)}>×</button>
            </div>
            <form onSubmit={handleSave}>
              <div className="mod-bd">

                {/* Row 1: Date · Movement Source Type */}
                <div className="fg">
                  <div className="fld">
                    <label>Date <span className="req">*</span></label>
                    <input className="inp" type="date" value={form.date||''} onChange={e=>setF('date',e.target.value)} required/>
                  </div>
                  <div className="fld">
                    <label>Movement Source Type <span style={{fontSize:10,color:'var(--txt2)',fontWeight:400,marginLeft:4}}>(Pickup Site)</span> <span className="req">*</span></label>
                    <window.FormSelect placeholder="— Select Pickup Site Type —" value={form.movementSourceType||''} onChange={v=>changeMST(v)} options={[...SITE_ENTITY_TYPES.map(o=>({value:o,label:o})), {value:'Debris',label:'Debris'}, {value:'Manual Adjustment',label:'Manual Adjustment'}]}/>
                  </div>
                </div>

                {/* Row 2: Dynamic Entity */}
                {form.movementSourceType&&MST_NEEDS_ENTITY.has(form.movementSourceType)&&(
                  <div className="fg">
                    <div className="fld full">
                      <label>{MST_ENTITY_LBL[form.movementSourceType]} <span className="req">*</span></label>
                      <window.FormSelect placeholder={'Select '+MST_ENTITY_LBL[form.movementSourceType]+'…'} value={form.entityId||''} onChange={v=>changeEntity(v)} options={dynEntities.map(e=>({value:e.id,label:e.name}))}/>
                      {dynEntities.length===0&&(
                        <div style={{fontSize:10.5,color:'var(--warn)',marginTop:3}}>
                          No {MST_ENTITY_LBL[form.movementSourceType]} records found. Add them in the relevant Master first.
                        </div>
                      )}
                    </div>
                  </div>
                )}

                {/* Source Stockyard — hidden for Stockyard/InternalStockyard MST; those transfers derive the
                     receiving yard from Destination Stockyard (destinationId) in the Destination section below. */}
                {form.movementSourceType && form.movementSourceType !== 'Stockyard' && form.movementSourceType !== 'Internal Stockyard' && (
                  <div className="fg">
                    <div className="fld full">
                      <label>Source Stockyard <span className="req">*</span></label>
                      <window.FormSelect placeholder="Select Stockyard" value={form.stockyardId||''} onChange={v=>setF('stockyardId',v)} options={stockyards.map(s=>({value:s.id,label:s.name}))}/>
                    </div>
                  </div>
                )}

                {/* ── Destination Section — required for route-based Transport Rate lookup ── */}
                {form.movementSourceType && form.movementSourceType !== 'Manual Adjustment' && (
                  <div style={{margin:'10px 0',padding:'12px 14px',background:'#F0F9FF',border:'1px solid #BAE6FD',borderRadius:8}}>
                    <div style={{fontWeight:700,fontSize:11.5,color:'#0369A1',marginBottom:10,display:'flex',alignItems:'center',gap:6}}>
                      <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M12 2C8.13 2 5 5.13 5 9c0 5.25 7 13 7 13s7-7.75 7-13c0-3.87-3.13-7-7-7z"/><circle cx="12" cy="9" r="2.5"/></svg>
                      Destination — determines Transport Rate from Rate Master
                    </div>
                    <div className="fg">
                      <div className="fld">
                        <label>Destination Type <span style={{fontSize:10,color:'var(--txt2)',fontWeight:400,marginLeft:4}}>(Delivery Site)</span> <span className="req">*</span></label>
                        <window.FormSelect placeholder="— Select Delivery Site Type —" value={form.destinationType||''} onChange={v=>changeDestType(v)} options={[...SITE_ENTITY_TYPES.map(t=>({value:t,label:t})), {value:'Others',label:'Others'}]}/>
                      </div>
                      {form.destinationType && form.destinationType !== 'Others' && (
                        <div className="fld">
                          <label>{DEST_ENTITY_LBL[form.destinationType]||('Destination — '+form.destinationType)} <span className="req">*</span></label>
                          <window.FormSelect placeholder={'Select '+(DEST_ENTITY_LBL[form.destinationType]||form.destinationType)+'…'} value={form.destinationId||''} onChange={v=>changeDestination(v)} options={dynDestEntities.map(e=>({value:e.id,label:e.name}))}/>
                          {dynDestEntities.length===0&&(
                            <div style={{fontSize:10.5,color:'var(--warn)',marginTop:3}}>No {form.destinationType} records found. Add them in the relevant Master first.</div>
                          )}
                        </div>
                      )}
                      {form.destinationType === 'Others' && (
                        <div className="fld">
                          <label>Destination Name <span className="req">*</span></label>
                          <input className="inp" value={form.destinationName||''}
                            onChange={e=>setForm(p=>({...p,destinationName:e.target.value}))}
                            placeholder="Enter destination name"/>
                          <div style={{fontSize:10,color:'var(--txt2)',marginTop:2}}>This exact name is stored and appears in all reports, exports and searches.</div>
                        </div>
                      )}
                    </div>
                    {/* Route preview with auto-fetched rate */}
                    {form.entityName && form.destinationName && (
                      <div style={{marginTop:8,background:'#fff',border:`1px solid ${autoRouteTrR?'#86EFAC':'#93C5FD'}`,borderRadius:6,padding:'7px 11px',display:'flex',alignItems:'center',gap:8,flexWrap:'wrap',fontSize:11.5}}>
                        <span style={{color:'var(--txt2)',fontSize:10,fontWeight:700,textTransform:'uppercase',letterSpacing:'.04em',flexShrink:0}}>Route</span>
                        <span style={{fontWeight:600,color:'var(--txt)'}}>{form.entityName}</span>
                        <span style={{color:'#93C5FD',fontSize:14}}>→</span>
                        <span style={{fontWeight:600,color:'var(--txt)'}}>{form.destinationName}</span>
                        {form.materialId && (
                          <span style={{color:'var(--txt3)',fontSize:10.5}}>· {(materials||[]).find(m=>m.id===form.materialId)?.name||''}</span>
                        )}
                        {autoRouteTrR && (
                          <span style={{marginLeft:'auto',fontWeight:700,color:'var(--ok)',fontSize:12,flexShrink:0,display:'flex',alignItems:'center',gap:4}}>
                            <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round"><path d="M5 13l4 4L19 7"/></svg>
                            ₹{Number(autoRouteTrR.ratePerTon).toLocaleString('en-IN')}/T
                            <span style={{fontSize:10,fontWeight:400,color:'var(--ok)'}}>from Rate Master</span>
                          </span>
                        )}
                        {!autoRouteTrR && form.materialId && (
                          <span style={{marginLeft:'auto',fontSize:10.5,color:'var(--err)',flexShrink:0}}>No matching rate found</span>
                        )}
                      </div>
                    )}
                    {routeErr && !autoRouteTrR && form.destinationName && form.materialId && (
                      <div style={{fontSize:10.5,color:'var(--err)',marginTop:6,lineHeight:1.4,display:'flex',alignItems:'flex-start',gap:4}}>
                        <svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" style={{flexShrink:0,marginTop:1}}><path d="m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3z"/><path d="M12 9v4"/><path d="M12 17h.01"/></svg>
                        {routeErr}
                      </div>
                    )}
                  </div>
                )}

                {/* Row 2b: Adjustment Type (Manual Adjustment only) */}
                {form.movementSourceType==='Manual Adjustment'&&(
                  <div className="fg">
                    <div className="fld">
                      <label>Adjustment Type <span className="req">*</span></label>
                      <window.FormSelect value={form.adjustType||'Adjustment In'} onChange={v=>setF('adjustType',v)} options={[{value:'Opening',label:'Opening Balance'},{value:'Adjustment In',label:'Adjustment In (Add)'},{value:'Adjustment Out',label:'Adjustment Out (Remove)'}]}/>
                    </div>
                  </div>
                )}

                {/* Row 3: Material (filtered) · Quantity */}
                <div className="fg">
                  <div className="fld">
                    <label>Material <span className="req">*</span></label>
                    <window.FormSelect placeholder="Select Material" value={form.materialId||''} onChange={v=>changeMaterial(v)} options={dynMaterials.map(m=>({value:m.id,label:m.name}))}/>
                    {form.movementSourceType&&dynMaterials.length!==materials.length&&(
                      <div style={{fontSize:10,color:'var(--info)',marginTop:2}}>
                        Showing {dynMaterials.length} of {materials.length} materials for selected source.
                      </div>
                    )}
                  </div>
                  <div className="fld">
                    <label>
                      {adjEnabled ? 'Net Quantity' : 'Quantity'}
                      {adjEnabled && <span style={{fontSize:10,color:'var(--txt2)',fontWeight:400,marginLeft:4}}>Customer Weighbridge</span>}
                      <span className="req">*</span>
                    </label>
                    <input className="inp" type="number" value={form.quantity||''} onChange={e=>setF('quantity',e.target.value)} required min="0" step="0.001" placeholder="0.000"/>
                    {adjEnabled&&<div style={{fontSize:10,color:'var(--info)',marginTop:2}}>Enter qty from customer’s weighbridge. Gross quantity is auto-calculated below.</div>}
                  </div>
                </div>

                {/* Inventory Quantity Adjustment — Optional, collapsed by default */}
                {form.materialId && (
                  <div style={{margin:'0 0 12px',border:'1px solid var(--bdr)',borderRadius:8,overflow:'hidden'}}>
                    {/* Header — always visible */}
                    <div onClick={()=>setAdjSectionOpen(v=>!v)}
                      style={{display:'flex',alignItems:'center',gap:8,padding:'9px 14px',cursor:'pointer',
                        background:adjSectionOpen?'#F0FDF4':'#FAFAF9',
                        borderBottom:adjSectionOpen?'1px solid #BBF7D0':'none',
                        userSelect:'none',transition:'background .15s'}}>
                      <svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round"
                        style={{transform:adjSectionOpen?'rotate(90deg)':'none',transition:'transform .2s',color:'var(--txt3)',flexShrink:0}}>
                        <polyline points="9 18 15 12 9 6"/>
                      </svg>
                      <span style={{fontWeight:600,fontSize:11.5,color:'var(--txt)'}}>Inventory Quantity Adjustment</span>
                      <span style={{fontSize:10,color:'var(--txt3)',fontWeight:400}}>(Optional)</span>
                      {adjEnabled && _netQtyR>0
                        ? <span style={{marginLeft:'auto',fontSize:10.5,fontWeight:700,color:'var(--ok)',display:'flex',alignItems:'center',gap:4,flexShrink:0}}>
                            <svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5"><path d="M5 13l4 4L19 7"/></svg>
                            Active — Inventory Deducted: {_invDedR.toFixed(3)} MT
                          </span>
                        : <span style={{marginLeft:'auto',fontSize:10,color:'var(--txt3)',flexShrink:0}}>no adjustment</span>
                      }
                    </div>
                    {/* Collapsible body */}
                    {adjSectionOpen && (
                      <div style={{padding:'12px 14px',background:'#F8FFF9'}}>
                        <label style={{display:'flex',alignItems:'center',gap:8,marginBottom:10,cursor:'pointer'}}>
                          <input type="checkbox" checked={adjEnabled} onChange={e=>setAdjEnabled(e.target.checked)}
                            style={{width:14,height:14,accentColor:'var(--ok)',cursor:'pointer'}}/>
                          <span style={{fontWeight:600,fontSize:12,color:'var(--txt)'}}>Enable Inventory Adjustment</span>
                          {matAdjConfig && (
                            <span style={{fontSize:10,color:'var(--ok)',marginLeft:4}}>
                              — {matAdjConfig.name}: {matAdjConfig.qtyAdjType||'Adjustment'} {matAdjConfig.qtyAdjPct||0}%
                            </span>
                          )}
                        </label>
                        {!adjEnabled && (
                          <div style={{fontSize:11,color:'var(--txt3)',paddingLeft:22}}>
                            Disabled — Inventory Deducted = Net Quantity{_netQtyR>0?` (${_netQtyR.toFixed(3)} MT)`:''}.
                          </div>
                        )}
                        {adjEnabled && (
                          <div>
                            <div style={{fontSize:10.5,color:'var(--txt2)',marginBottom:10,lineHeight:1.5}}>
                              Only inventory is affected. Sales, billing, revenue and transport always use Net Quantity.
                            </div>
                            <div className="fg">
                              <div className="fld">
                                <label style={{color:'#166534',fontSize:11}}>Adjustment Type</label>
                                <window.FormSelect placeholder="— Select Type —"
                                  value={adjType}
                                  onChange={v=>{setAdjType(v);if(v!=='Other')setAdjCustomType('');}} style={{borderColor:'#86EFAC'}}
                                  options={adjTypeOptions.map(t=>({value:t,label:t}))}/>
                                {adjType==='Other' && (
                                  <input className="inp" value={adjCustomType} onChange={e=>setAdjCustomType(e.target.value)}
                                    placeholder="Enter custom adjustment name" style={{marginTop:4,borderColor:'#86EFAC'}}/>
                                )}
                              </div>
                              <div className="fld">
                                <label style={{color:'#166534',fontSize:11}}>
                                  Adjustment %
                                  {matAdjConfig?.qtyAdjAllowOverride
                                    ? <span style={{color:'var(--ok)',fontWeight:400,marginLeft:4}}>· editable</span>
                                    : matAdjConfig
                                      ? <span style={{color:'var(--txt2)',fontWeight:400,marginLeft:4}}>· from master</span>
                                      : <span style={{color:'var(--txt2)',fontWeight:400,marginLeft:4}}>· enter value</span>}
                                </label>
                                <input className="inp" type="number" value={adjPct}
                                  onChange={e=>{if(!matAdjConfig||matAdjConfig.qtyAdjAllowOverride)setAdjPct(Math.max(0,Math.min(99,parseFloat(e.target.value)||0)));}} 
                                  readOnly={!!matAdjConfig&&!matAdjConfig.qtyAdjAllowOverride}
                                  step="0.01" min="0" max="99"
                                  style={!!matAdjConfig&&!matAdjConfig.qtyAdjAllowOverride
                                    ?{background:'#F9FAFB',cursor:'default',fontWeight:700,color:'#166534'}
                                    :{borderColor:'#86EFAC'}}/>
                              </div>
                            </div>
                            <div className="fg">
                              <div className="fld">
                                <label style={{color:'#166534',fontSize:11}}>Gross Quantity <span style={{fontWeight:400,color:'var(--txt2)'}}>auto · read-only</span></label>
                                <input className="inp" type="text" readOnly
                                  value={_netQtyR>0?_grossQtyR.toFixed(3)+' MT':'—'}
                                  style={{background:'#F9FAFB',cursor:'default',fontWeight:700,color:'var(--ok)'}}/>
                                {_netQtyR>0 && <div style={{fontSize:9.5,color:'#166534',marginTop:2}}>{_netQtyR.toFixed(3)} ÷ (1 − {adjPct}/100) = {_grossQtyR.toFixed(3)}</div>}
                              </div>
                              <div className="fld">
                                <label style={{color:'#166534',fontSize:11}}>Inventory Deducted <span style={{fontWeight:400,color:'var(--txt2)'}}>= Gross · read-only</span></label>
                                <input className="inp" type="text" readOnly
                                  value={_netQtyR>0?_invDedR.toFixed(3)+' MT':'—'}
                                  style={{background:'#FFF7ED',cursor:'default',fontWeight:700,color:'var(--or)',border:'1.5px solid var(--or-bdr)'}}/>
                                {_netQtyR>0 && <div style={{fontSize:9.5,color:'var(--or)',marginTop:2}}>Deducted from stock register</div>}
                              </div>
                            </div>
                          </div>
                        )}
                      </div>
                    )}
                  </div>
                )}

                {/* Row 4: Rate (auto or manual) */}
                <div className="fg">
                  <div className="fld">
                    {isManualMST ? (
                      <>
                        <label>Rate ₹/Ton</label>
                        <input className="inp" type="number" value={form.manualRate||''} onChange={e=>setF('manualRate',e.target.value)} min="0" step="0.01" placeholder="0.00"/>
                      </>
                    ) : (
                      <>
                        <label>Rate ₹/Ton <span style={{fontSize:10,color:'var(--ok)',fontWeight:400,marginLeft:4}}>auto-fetched · read-only</span></label>
                        <input className="inp" type="text" value={rateDisplay||''} readOnly
                          style={{background:'#F9FAFB',cursor:'default',fontWeight:600,
                            color: autoRate ? 'var(--ok)' : (form.entityId&&form.materialId ? 'var(--err)' : 'var(--txt3)')}}/>
                        {rateErr&&(
                          <div style={{fontSize:10.5,color:'var(--err)',marginTop:3,lineHeight:1.4}}>{rateErr}</div>
                        )}
                        {autoRate&&(
                          <div style={{fontSize:10,color:'var(--ok)',marginTop:2}}>
                            PO: {autoRate.poNumber||'—'} · GST: {autoRate.gst||'5'}%
                          </div>
                        )}
                      </>
                    )}
                  </div>
                  <div className="fld">
                    <label>Material Value <span style={{fontSize:10,color:'var(--txt2)',fontWeight:400,marginLeft:4}}>auto</span></label>
                    <input className="inp" type="text" readOnly
                      value={(()=>{
                        const q=parseFloat(form.quantity)||0;
                        const r=isManualMST?(parseFloat(form.manualRate)||0):(autoRate?.rate||0);
                        return q&&r ? window.fmtCur(q*r) : '—';
                      })()}
                      style={{background:'#F9FAFB',cursor:'default',fontWeight:600,color:'var(--ok)'}}/>
                  </div>
                </div>

                {/* Row 5: Business Document Number · Notes */}
                <div className="fg">
                  <div className="fld">
                    <label>{docLabel}</label>
                    <input className="inp" value={form.documentNumber||''} onChange={e=>setF('documentNumber',e.target.value)} placeholder={`e.g. ${docLabel.split(' ').map(w=>w[0]).join('')}-001`}/>
                  </div>
                  <div className="fld">
                    <label>Notes</label>
                    <input className="inp" value={form.notes||''} onChange={e=>setF('notes',e.target.value)} placeholder="Optional"/>
                  </div>
                </div>

                {/* Transport Section — hidden for Sale movements */}
                {showTransport ? (
                <div style={{marginTop:14,paddingTop:12,borderTop:'2px solid #FEF3E8'}}>
                  <div style={{color:'var(--or)',fontWeight:700,fontSize:12,marginBottom:10}}>
                    Transport Details <span style={{fontSize:10.5,fontWeight:400,color:'var(--txt2)'}}>— auto-generates transport record · auto-fetches rate from Transport Rate Master</span>
                  </div>
                  <div className="fg">
                    <div className="fld">
                      <label>Transporter</label>
                      <window.FormSelect placeholder="Select Transporter (optional)" value={form.transporterMasterId||''} onChange={v=>changeTransporter(v)} options={syrTmActive.map(t=>({value:t.id,label:t.name}))}/>
                    </div>
                    <div className="fld">
                      <label>Vehicle{syrTmVehicles.length>0&&<span style={{fontSize:10,color:'var(--txt2)',fontWeight:400,marginLeft:4}}>({syrTmVehicles.length} vehicles)</span>}</label>
                      <window.FormSelect placeholder={!form.transporterMasterId?'Select transporter first…':'Select Vehicle'} value={form.vehicleFull||''} onChange={v=>setF('vehicleFull',v)} disabled={!form.transporterMasterId} style={{fontFamily:'var(--font)',fontWeight:600}} options={syrTmVehicles.map(v=>({value:v.vehicleNumber,label:v.vehicleNumber+(v.vehicleType?' ('+v.vehicleType+')':'')}))}/>
                    </div>
                    <div className="fld">
                      <label>Transport Rate
                        <span style={{fontSize:10,fontWeight:400,marginLeft:4,color:autoRouteTrR?'var(--ok)':'var(--txt2)'}}>auto — from Transport Rate Master</span>
                      </label>
                      <input className="inp" type="text" readOnly
                        value={
                          autoRouteTrR
                            ? `₹${Number(autoRouteTrR.ratePerTon).toLocaleString('en-IN')}/T — ${form.entityName||''}  →  ${form.destinationName||''}`
                            : !form.destinationType
                              ? 'Select Destination Type first'
                              : !form.destinationName
                                ? 'Select Destination first'
                                : !form.materialId
                                  ? 'Select Material first'
                                  : 'No matching route in Transport Rate Master'
                        }
                        style={{background:'#F9FAFB',cursor:'default',fontWeight:600,fontSize:11,
                          color:autoRouteTrR?'var(--ok)':(!form.destinationType||!form.destinationName||!form.materialId)?'var(--txt3)':'var(--err)'}}/>
                      {autoRouteTrR && (
                        <div style={{fontSize:10,color:'var(--ok)',marginTop:2,display:'flex',alignItems:'center',gap:4}}>
                          <svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round"><path d="M5 13l4 4L19 7"/></svg>
                          Route match confirmed · ₹{Number(autoRouteTrR.ratePerTon).toLocaleString('en-IN')} per Ton
                        </div>
                      )}
                    </div>
                  </div>
                </div>
                ) : (form.movementSourceType && (
                  <div style={{marginTop:12,padding:'9px 14px',background:'#FFF7ED',border:'1px solid var(--or-bdr)',borderRadius:8,fontSize:11.5,color:'var(--txt2)',display:'flex',alignItems:'center',gap:7}}>
                    <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" style={{color:'var(--or)',flexShrink:0}}><circle cx="12" cy="12" r="10"/><line x1="12" y1="8" x2="12" y2="12"/><line x1="12" y1="16" x2="12.01" y2="16"/></svg>
                    Transport details are not required for <strong style={{marginLeft:3,marginRight:3}}>{form.movementSourceType}</strong> movements — transport was recorded during the Sales Order.
                  </div>
                ))}

                {/* Financial Summary */}
                {/* netQty = customer weighbridge qty (transport payment basis) */}
                {/* invQty = inventory deducted qty (material value basis)      */}
                <SYFinSummary
                  netQty={_netQtyR}
                  invQty={_invDedR}
                  matRate={isManualMST?(form.manualRate||0):(autoRate?.rate||0)}
                  trRate={showTransport?(autoRouteTrR?.ratePerTon||0):0}
                />

              </div>
              <div className="mod-ft">
                <button type="button" className="btn btn-wh" onClick={()=>setModal(false)}>Cancel</button>
                <button type="submit" className="btn btn-or">{editMovId?'Update Movement':'Record Movement'}</button>
              </div>
            </form>
          </div>
        </div>
      )}
    </div>
  );
}
window.SYRegister = SYRegister;

// ── Yard Transfers ─────────────────────────────────────────────────────────
function SYTransfers({ stockyards, materials, onRefresh }) {
  window.useStoreSync();
  const transfers = Store.all('syTransfers') || [];
  const { session, companyId } = srCtx(AppCtx);
  const [modal, setModal] = srSt(false);
  const [delId, setDelId] = srSt(null);
  const [form,  setForm]  = srSt({});
  const [pg,    setPg]    = srSt(1);
  const [expId, setExpId] = srSt(null);
  const [fSY,   setFSY]   = srSt('');
  const [fMat,  setFMat]  = srSt('');
  const [fTp,   setFTp]   = srSt('');
  const [dFrom, setDFrom] = srSt('');
  const [dTo,   setDTo]   = srSt('');
  const [autoMatRate, setAutoMatRate] = srSt(0);   // from source yard avg
  const [autoTrRate,  setAutoTrRate]  = srSt(null); // from transport PO
  const PER = 50;

  // Transporter Master integration
  const [sytTmAll,  setSytTmAll]  = srSt(()=>Store.all('transporterMaster','group'));
  const [sytVehAll, setSytVehAll] = srSt(()=>Store.all('vehicleMaster','group')||[]);
  srEf(()=>{const u=Store.on(()=>{setSytTmAll(Store.all('transporterMaster','group'));setSytVehAll(Store.all('vehicleMaster','group')||[]);});return u;},[]);
  const sytTmActive   = sytTmAll.filter(t=>t.status==='Active'||!t.status);
  const sytTmVehicles = srMemo(()=>form.transporterMasterId?sytVehAll.filter(v=>v.transporterId===form.transporterMasterId&&(v.status==='Active'||!v.status)):[],[sytVehAll,form.transporterMasterId]);

  // Auto-fetch material rate from source stockyard
  srEf(()=>{
    if (!modal) return;
    setAutoMatRate(sourceYardAvgRate(form.fromStockyardId,form.materialId));
  },[form.fromStockyardId,form.materialId,modal]);

  // Auto-fetch transport rate
  srEf(()=>{
    if (!modal) return;
    setAutoTrRate(mstFetchTrRate(form.transporterMasterId,form.materialId,form.fromStockyardId,companyId));
  },[form.transporterMasterId,form.materialId,form.fromStockyardId,modal,companyId]);

  const setF      = (k,v) => setForm(p=>({...p,[k]:v}));
  const toggleTrf = id    => setExpId(v=>v===id?null:id);

  function changeTpFrom(id) {
    setForm(p=>({...p,transporterMasterId:id,transporterName:(sytTmActive.find(t=>t.id===id)||{}).name||'',vehicleFull:''}));
  }

  function openAdd() {
    setForm({ date:new Date().toISOString().slice(0,10), status:'Completed', quantity:'', transporterMasterId:'', transporterName:'', vehicleFull:'', challan:'', notes:'' });
    setAutoMatRate(0); setAutoTrRate(null);
    setModal(true);
  }

  function handleSave(e) {
    e.preventDefault();
    if (form.fromStockyardId===form.toStockyardId){ window.toast&&window.toast('Source and Destination must be different','er'); return; }
    if (!form.materialId){ window.toast&&window.toast('Select a Material','er'); return; }
    const q=parseFloat(form.quantity)||0;
    if (!q||q<=0){ window.toast&&window.toast('Enter a valid quantity','er'); return; }

    const r      = autoMatRate||0;
    const trRate = autoTrRate?.rate||0;
    const val    = q*r;
    const trCost = q*trRate;
    const coId   = (Store.byId('stockyards',form.fromStockyardId)||{}).companyId||'';

    const tr = Store.add('syTransfers',{
      ...form, quantity:q, rate:r, value:val,
      transportRate:trRate, transportCost:trCost, totalCost:val+trCost,
      createdBy:session?.userName||'System',
    });
    const ref = 'SYT-'+tr.id.slice(-6).toUpperCase();

    Store.add('stockMovements',{
      date:form.date, stockyardId:form.fromStockyardId, materialId:form.materialId,
      type:'Transfer Out', quantity:q, rate:r, value:val, reference:ref,
      transporterMasterId:form.transporterMasterId||'', transporterName:form.transporterName||'', vehicleFull:form.vehicleFull||'',
      companyId:coId, createdBy:session?.userName||'System', transferId:tr.id,
    });
    Store.add('stockMovements',{
      date:form.date, stockyardId:form.toStockyardId, materialId:form.materialId,
      type:'Transfer In', quantity:q, rate:r, value:val, reference:ref,
      transporterMasterId:form.transporterMasterId||'', transporterName:form.transporterName||'', vehicleFull:form.vehicleFull||'',
      companyId:(Store.byId('stockyards',form.toStockyardId)||{}).companyId||'',
      createdBy:session?.userName||'System', transferId:tr.id,
    });
    Store.addLog('CREATE','Yard Transfer',
      `${Store.name('stockyards',form.fromStockyardId)} → ${Store.name('stockyards',form.toStockyardId)}: ${q}T @ ₹${r}/T`
    );

    if (form.transporterMasterId&&form.vehicleFull) {
      Store.add('transportEntries',{
        date:form.date, companyId:coId,
        transporterId:form.transporterMasterId, transporter:form.transporterName||'',
        vehicleFull:form.vehicleFull, materialId:form.materialId,
        material:Store.name('materials',form.materialId),
        quantity:q, unit:(Store.byId('materials',form.materialId)||{}).unit||'MT',
        status:form.status||'Completed', source:'Auto Generated', sourceModule:'STOCKYARD',
        _autoGenerated:true, _yardTransferId:tr.id,
        _fromStockyardId:form.fromStockyardId, _fromStockyardName:Store.name('stockyards',form.fromStockyardId),
        _toStockyardId:form.toStockyardId, _toStockyardName:Store.name('stockyards',form.toStockyardId),
        reference:ref, challanNumber:form.challan||'',
        createdBy:session?.userName||'System',
        _creationTimestamp:new Date().toISOString(),
        lastUpdated:new Date().toISOString().slice(0,10),
      });
    }
    setModal(false); onRefresh();
    window.toast&&window.toast('Yard transfer created','ok');
  }

  function handleDelete() {
    const linked=(Store.all('stockMovements')||[]).filter(m=>m.transferId===delId);
    linked.forEach(m=>Store.del('stockMovements',m.id));
    Store.del('syTransfers',delId);
    Store.addLog('DELETE','Yard Transfer','Deleted');
    setDelId(null); onRefresh();
    window.toast&&window.toast('Transfer deleted','ok');
  }

  // Materials available in source yard
  const srcMaterials = srMemo(()=>{
    if (!form.fromStockyardId) return materials;
    const mids = new Set((Store.all('stockMovements')||[]).filter(m=>m.stockyardId===form.fromStockyardId).map(m=>m.materialId));
    const f = (materials||[]).filter(m=>mids.has(m.id));
    return f.length>0?f:materials;
  },[form.fromStockyardId,materials]);

  const filtered = srMemo(()=>{
    return (transfers||[]).filter(t=>{
      if(fSY&&t.fromStockyardId!==fSY&&t.toStockyardId!==fSY)return false;
      if(fMat&&t.materialId!==fMat)return false;
      if(fTp&&t.transporterMasterId!==fTp)return false;
      if(dFrom&&(t.date||'')<dFrom)return false;
      if(dTo&&(t.date||'')>dTo)return false;
      return true;
    });
  },[transfers,fSY,fMat,fTp,dFrom,dTo]);
  const trfTotQty = srMemo(()=>filtered.reduce((s,t)=>s+(parseFloat(t.quantity)||0),0),[filtered]);
  const trfTotVal = srMemo(()=>filtered.reduce((s,t)=>s+(parseFloat(t.value)||0),0),[filtered]);
  const paged    = filtered.slice((pg-1)*PER, pg*PER);
  const totalPgs = Math.ceil(filtered.length/PER);

  return (
    <div>
      <div className="ph" style={{marginBottom:10}}>
        <div><h1 style={{fontSize:15}}>Yard Transfers</h1><p style={{fontSize:11.5,color:'var(--txt2)'}}>Move material between stockyards — rate auto-loaded from source yard · click any row to drill down</p></div>
        <div className="ph-act"><button className="btn btn-or" onClick={openAdd}><svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg> Add Transfer</button></div>
      </div>
      <div className="frow" style={{marginBottom:8}}>
        <div className="fp-fld"><label style={{fontSize:11,color:'var(--txt2)',marginBottom:2,display:'block'}}>From Date</label><input type="date" className="inp" value={dFrom} onChange={e=>{setDFrom(e.target.value);setPg(1);}}/></div>
        <div className="fp-fld"><label style={{fontSize:11,color:'var(--txt2)',marginBottom:2,display:'block'}}>To Date</label><input type="date" className="inp" value={dTo} onChange={e=>{setDTo(e.target.value);setPg(1);}}/></div>
        <window.FiltSelect placeholder="All Stockyards" value={fSY} onChange={v=>{setFSY(v);setPg(1);}} options={(stockyards||[]).map(s=>({value:s.id,label:s.name}))}/>
        <window.FiltSelect placeholder="All Materials" value={fMat} onChange={v=>{setFMat(v);setPg(1);}} options={(materials||[]).map(m=>({value:m.id,label:m.name}))}/>
        <window.FiltSelect placeholder="All Transporters" value={fTp} onChange={v=>{setFTp(v);setPg(1);}} options={sytTmActive.map(t=>({value:t.id,label:t.name}))}/>
        {(fSY||fMat||fTp||dFrom||dTo)&&<button className="btn btn-gh btn-sm" onClick={()=>{setFSY('');setFMat('');setFTp('');setDFrom('');setDTo('');setPg(1);}}>Clear</button>}
        <span className="f-cnt">{filtered.length} transfer{filtered.length!==1?'s':''}</span>
      </div>
      <div className="card">
        <div className="tbl-w">
          <table className="tbl">
            <thead><tr>
              <th style={{width:28}}></th>
              <th>DATE</th><th>FROM STOCKYARD</th><th>TO STOCKYARD</th><th>MATERIAL</th>
              <th>QUANTITY</th><th>UNIT</th><th>VALUE</th><th>TRANSPORTER</th><th>VEHICLE</th><th>CHALLAN</th><th>STATUS</th><th>ACTIONS</th>
            </tr></thead>
            <tbody>
              {paged.length===0
                ? <tr className="empty"><td colSpan="13" style={{textAlign:'center',padding:36,color:'var(--txt2)'}}>{(transfers||[]).length===0?'No yard transfers. Click "Add Transfer" to move material between stockyards.':'No transfers match the current filters.'}</td></tr>
                : paged.map(t=>{
                  const mat=(materials||[]).find(m=>m.id===t.materialId)||{unit:'MT'}; const isExp=expId===t.id;
                  return (
                    <React.Fragment key={t.id}>
                      <tr onClick={()=>toggleTrf(t.id)} style={{cursor:'pointer',background:isExp?'#EFF6FF':''}}>
                        <td style={{textAlign:'center',padding:'0 8px'}}><window.SYChevron open={isExp} color="#1D4ED8"/></td>
                        <td style={{whiteSpace:'nowrap'}}>{window.fmtDate(t.date)}</td>
                        <td style={{fontWeight:500}}>{Store.name('stockyards',t.fromStockyardId)}</td>
                        <td style={{fontWeight:500}}>{Store.name('stockyards',t.toStockyardId)}</td>
                        <td>{Store.name('materials',t.materialId)}</td>
                        <td style={{fontWeight:600}}>{Number(t.quantity||0).toFixed(3)}</td>
                        <td style={{color:'var(--txt2)'}}>{mat.unit||'MT'}</td>
                        <td style={{fontWeight:600,color:'var(--or)'}}>{t.value?window.fmtCur(t.value):'—'}</td>
                        <td style={{fontSize:11.5,color:'var(--txt2)'}}>{t.transporterName||'—'}</td>
                        <td style={{fontFamily:'var(--font)',fontSize:11}}>{t.vehicleFull||t.vehicleNum||'—'}</td>
                        <td style={{fontFamily:'var(--font)',fontSize:11.5}}>{t.challan||'—'}</td>
                        <td><window.Badge v={t.status||'Completed'}/></td>
                        <td onClick={e=>e.stopPropagation()}>
                          <button className="btn btn-rd btn-sm" onClick={()=>setDelId(t.id)}>Delete</button>
                        </td>
                      </tr>
                      {isExp&&(
                        <tr><td colSpan={13} style={{padding:0,borderBottom:'2px solid #BFDBFE'}}>
                          <window.SYTransferDrill t={t} materials={materials}/>
                        </td></tr>
                      )}
                    </React.Fragment>
                  );
                })}
            </tbody>
            {filtered.length>0&&(
              <tfoot><tr style={{background:'#FFF7ED'}}>
                <td style={{borderTop:'2px solid var(--or-bdr)'}}></td>
                <td colSpan={4} style={{fontWeight:700,fontSize:11.5,color:'var(--txt2)',padding:'8px 10px',borderTop:'2px solid var(--or-bdr)'}}>TOTALS — {filtered.length} transfer{filtered.length!==1?'s':''}</td>
                <td style={{fontWeight:700,color:'var(--or)',padding:'8px 10px',borderTop:'2px solid var(--or-bdr)'}}>{trfTotQty.toFixed(3)}</td>
                <td style={{borderTop:'2px solid var(--or-bdr)'}}></td>
                <td style={{fontWeight:700,color:'var(--ok)',padding:'8px 10px',borderTop:'2px solid var(--or-bdr)'}}>{window.fmtCur(trfTotVal)}</td>
                <td colSpan={5} style={{borderTop:'2px solid var(--or-bdr)'}}></td>
              </tr></tfoot>
            )}
          </table>
        </div>
      </div>
      {totalPgs>1&&<div className="pag"><button className="pg-b" onClick={()=>setPg(1)} disabled={pg===1}>«</button><button className="pg-b" onClick={()=>setPg(p=>p-1)} disabled={pg===1}>‹</button><span className="pg-inf">Page {pg} of {totalPgs}</span><button className="pg-b" onClick={()=>setPg(p=>p+1)} disabled={pg===totalPgs}>›</button><button className="pg-b" onClick={()=>setPg(totalPgs)} disabled={pg===totalPgs}>»</button></div>}

      {/* ── Add Transfer Modal ── */}
      {modal&&(
        <div className="mbg">
          <div className="mod mod-lg">
            <div className="mod-hd"><h2>Add Yard Transfer</h2><button className="mod-x" onClick={()=>setModal(false)}>×</button></div>
            <form onSubmit={handleSave}>
              <div className="mod-bd">

                {/* Row 1: Date · From · To */}
                <div className="fg3" style={{marginBottom:12}}>
                  <div className="fld">
                    <label>Transfer Date <span className="req">*</span></label>
                    <input className="inp" type="date" value={form.date||''} onChange={e=>setF('date',e.target.value)} required/>
                  </div>
                  <div className="fld">
                    <label>From Stockyard <span className="req">*</span></label>
                    <window.FormSelect placeholder="Select Source" value={form.fromStockyardId||''} onChange={v=>{setF('fromStockyardId',v);setForm(p=>({...p,fromStockyardId:v,materialId:''}));}} options={stockyards.filter(s=>s.status==='Active').map(s=>({value:s.id,label:s.name}))}/>
                  </div>
                  <div className="fld">
                    <label>To Stockyard <span className="req">*</span></label>
                    <window.FormSelect placeholder="Select Destination" value={form.toStockyardId||''} onChange={v=>setF('toStockyardId',v)}
                      style={form.fromStockyardId&&form.toStockyardId&&form.fromStockyardId===form.toStockyardId?{borderColor:'var(--err)'}:{}}
                      options={stockyards.filter(s=>s.status==='Active').map(s=>({value:s.id,label:s.name}))}/>
                    {form.fromStockyardId&&form.toStockyardId&&form.fromStockyardId===form.toStockyardId&&(
                      <span style={{fontSize:10.5,color:'var(--err)',marginTop:2,display:'block'}}>Source and Destination cannot be the same.</span>
                    )}
                  </div>
                </div>

                {/* Row 2: Material (from source yard) · Quantity · Rate (auto) */}
                <div className="fg3" style={{marginBottom:12}}>
                  <div className="fld">
                    <label>Material <span className="req">*</span></label>
                    <window.FormSelect placeholder="Select Material" value={form.materialId||''} onChange={v=>setF('materialId',v)} options={srcMaterials.map(m=>({value:m.id,label:m.name}))}/>
                    {form.fromStockyardId&&srcMaterials.length!==materials.length&&(
                      <div style={{fontSize:10,color:'var(--info)',marginTop:2}}>Showing materials in source yard only.</div>
                    )}
                  </div>
                  <div className="fld">
                    <label>Quantity <span className="req">*</span></label>
                    <input className="inp" type="number" value={form.quantity||''} onChange={e=>setF('quantity',e.target.value)} required min="0" step="0.001" placeholder="0.000"/>
                  </div>
                  <div className="fld">
                    <label>Transfer Rate ₹/Ton <span style={{fontSize:10,color:'var(--ok)',fontWeight:400,marginLeft:4}}>auto from source yard</span></label>
                    <input className="inp" type="text" readOnly
                      value={autoMatRate>0 ? `₹${Number(autoMatRate).toLocaleString('en-IN')} — Source Avg` : (form.fromStockyardId&&form.materialId ? 'No stock in source yard' : '—')}
                      style={{background:'#F9FAFB',cursor:'default',fontWeight:600,color:autoMatRate>0?'var(--ok)':'var(--txt3)'}}/>
                    {autoMatRate>0&&(
                      <div style={{fontSize:10,color:'var(--ok)',marginTop:2}}>Weighted avg of inward movements at source yard</div>
                    )}
                  </div>
                </div>

                {/* Row 3: Transfer Value (auto) */}
                <div className="fg3" style={{marginBottom:12}}>
                  <div className="fld">
                    <label>Transfer Value <span style={{fontSize:10,color:'var(--txt2)',fontWeight:400,marginLeft:4}}>auto</span></label>
                    <input className="inp" type="text" readOnly
                      value={(()=>{const q=parseFloat(form.quantity)||0;return q&&autoMatRate?window.fmtCur(q*autoMatRate):'—';})()}
                      style={{background:'#F9FAFB',cursor:'default',fontWeight:600,color:'var(--ok)'}}/>
                  </div>
                  <div className="fld">
                    <label>Transfer Challan</label>
                    <input className="inp" value={form.challan||''} onChange={e=>setF('challan',e.target.value)} placeholder="TC-001"/>
                  </div>
                  <div className="fld">
                    <label>Status</label>
                    <window.FormSelect value={form.status||'Completed'} onChange={v=>setF('status',v)} options={[{value:'Pending',label:'Pending'},{value:'In Transit',label:'In Transit'},{value:'Completed',label:'Completed'}]}/>
                  </div>
                </div>

                {/* Transport Section */}
                <div style={{marginTop:4,paddingTop:12,borderTop:'2px solid #FEF3E8'}}>
                  <div style={{color:'var(--or)',fontWeight:700,fontSize:12,marginBottom:10}}>
                    Transport Details <span style={{fontSize:10.5,fontWeight:400,color:'var(--txt2)'}}>— transport rate auto-fetched from Transport Rate Master</span>
                  </div>
                  <div className="fg3">
                    <div className="fld">
                      <label>Transporter <span className="req">*</span></label>
                      <window.FormSelect placeholder="Select Transporter" value={form.transporterMasterId||''} onChange={v=>changeTpFrom(v)} options={sytTmActive.map(t=>({value:t.id,label:t.name}))}/>
                      {sytTmActive.length===0&&<div style={{fontSize:10.5,color:'var(--warn)',marginTop:3}}>No active transporters. Add in Transporter Master first.</div>}
                    </div>
                    <div className="fld">
                      <label>Vehicle Number{sytTmVehicles.length>0&&<span style={{fontSize:10,color:'var(--txt2)',fontWeight:400,marginLeft:4}}>({sytTmVehicles.length})</span>}</label>
                      <window.FormSelect placeholder={!form.transporterMasterId?'Select transporter first…':'Select Vehicle'} value={form.vehicleFull||''} onChange={v=>setF('vehicleFull',v)} disabled={!form.transporterMasterId} style={{fontFamily:'var(--font)',fontWeight:600}} options={sytTmVehicles.map(v=>({value:v.vehicleNumber,label:v.vehicleNumber+(v.vehicleType?' ('+v.vehicleType+')':'')}))}/>
                    </div>
                    <div className="fld">
                      <label>Transport Rate <span style={{fontSize:10,color:'var(--ok)',fontWeight:400,marginLeft:4}}>auto</span></label>
                      <input className="inp" type="text" readOnly
                        value={autoTrRate ? `₹${Number(autoTrRate.rate).toLocaleString('en-IN')} — ${autoTrRate.poNumber||'PO'}` : (form.transporterMasterId&&form.materialId?'No Transport PO':'—')}
                        style={{background:'#F9FAFB',cursor:'default',fontWeight:600,color:autoTrRate?'var(--ok)':'var(--txt3)'}}/>
                    </div>
                  </div>
                  <div className="fg" style={{marginTop:8}}>
                    <div className="fld full">
                      <label>Remarks</label>
                      <textarea className="tarea" value={form.notes||''} onChange={e=>setF('notes',e.target.value)} rows={2} placeholder="Optional remarks…"></textarea>
                    </div>
                  </div>
                </div>

                {/* Financial Summary */}
                <SYFinSummary
                  qty={form.quantity}
                  matRate={autoMatRate||0}
                  trRate={autoTrRate?.rate||0}
                />

              </div>
              <div className="mod-ft">
                <button type="button" className="btn btn-wh" onClick={()=>setModal(false)}>Cancel</button>
                <button type="submit" className="btn btn-or">Create Transfer</button>
              </div>
            </form>
          </div>
        </div>
      )}
      {delId&&<window.Confirm onOk={handleDelete} onCancel={()=>setDelId(null)}/>}
    </div>
  );
}
window.SYTransfers = SYTransfers;
