const TODAY = new Date('2026-11-05T09:00:00');
const d = (s) => new Date(s + 'T12:00:00');
const daysAgo = (n) => { const x = new Date(TODAY); x.setDate(x.getDate() - n); return x.toISOString(); };
const daysFrom = (n) => { const x = new Date(TODAY); x.setDate(x.getDate() + n); return x.toISOString().slice(0, 10); };
const STATUSES = ['Draft','Confirmed','Purchased','In Production','Shipped','In Transit','Arrived','Delivered','Stuck','Cancelled'];
const CLOSED = ['Delivered','Cancelled'];
const CONTAINER_STATUSES = ['Booked','Loading','Departed','At Sea','At Port','Customs Hold','Stuck','Delivered'];

const CLIENTS = [
  { id:'c1', name:'Marlin Bay Builders', contact:'Rachel Dawson', email:'rachel@marlinbay.com', password:'client' },
  { id:'c2', name:'Coral Ridge Homes', contact:'Tom Whitaker', email:'tom@coralridge.com', password:'client' },
  { id:'c3', name:'Biscayne Interiors', contact:'Anna Fletcher', email:'anna@biscayneint.com', password:'client' },
  { id:'c4', name:'Keys Marine Supply', contact:'Dale Hopkins', email:'dale@keysmarine.com', password:'client' },
];
const SUPPLIERS = [
  { id:'s1', name:'Foshan Tile Works', country:'China' },
  { id:'s2', name:'Guangzhou Sanitary Co.', country:'China' },
  { id:'s3', name:'Vietnam Hardwoods Ltd', country:'Vietnam' },
  { id:'s4', name:'Istanbul Stone Export', country:'Türkiye' },
  { id:'s5', name:'Ningbo Fixtures Group', country:'China' },
];
const USERS = [
  { id:'u1', name:'Mark Sutton', role:'manager', email:'mark@soflolg.com', password:'demo' },
  { id:'u2', name:'Laura Parker', role:'finance', email:'laura@soflolg.com', password:'demo' },
];

const hist = (arr) => arr.map(([n, event, by]) => ({ at: daysAgo(n), event, by: by || 'Mark Sutton' }));
const notes = (arr) => arr.map(([n, text]) => ({ at: daysAgo(n), text, by: 'Mark Sutton' }));

const CONTAINERS = [
  { id:'MSKU4471023', origin:'Shenzhen, CN', destination:'Port Miami, US', etd:'2026-09-18', eta:'2026-10-22', status:'Customs Hold', updatedAt:daysAgo(9), notes:notes([[9,'CBP exam requested. Broker says 1–2 more weeks.'],[14,'Arrived Port Miami, awaiting release.'],[48,'Departed Yantian on schedule.']]) },
  { id:'TGHU8820916', origin:'Ningbo, CN', destination:'Port Everglades, US', etd:'2026-10-02', eta:'2026-11-08', status:'At Sea', updatedAt:daysAgo(1), notes:notes([[1,'Vessel MSC Aurora, ETA unchanged.'],[12,'Transshipped at Busan.']]) },
  { id:'CMAU2203388', origin:'Haiphong, VN', destination:'Port Miami, US', etd:'2026-08-05', eta:'2026-09-14', status:'Stuck', updatedAt:daysAgo(3), notes:notes([[3,'Still held in Cristobal. Shipping line quoting demurrage, disputing.'],[30,'Rolled at Panama transshipment, no new vessel assigned.'],[60,'Departed Haiphong.']]) },
  { id:'OOLU6619204', origin:'Izmir, TR', destination:'Port Everglades, US', etd:'2026-10-20', eta:'2026-11-19', status:'Departed', updatedAt:daysAgo(7), notes:notes([[7,'Loaded and departed Izmir.']]) },
  { id:'MSKU3390117', origin:'Foshan, CN', destination:'Port Miami, US', etd:'2026-11-12', eta:'2026-12-16', status:'Booked', updatedAt:daysAgo(2), notes:notes([[2,'Booking confirmed with Maersk. Cutoff Nov 10.']]) },
  { id:'HLXU7748850', origin:'Shenzhen, CN', destination:'Port Miami, US', etd:'2026-08-28', eta:'2026-10-01', status:'Delivered', updatedAt:daysAgo(28), notes:notes([[28,'Delivered to Coral Ridge yard, signed by T. Whitaker.'],[31,'Released, trucking booked.']]) },
];

const ORDERS = [
  { id:'SO-1041', clientId:'c2', supplierId:'s1', priority:'Normal', requestedDate:'2026-10-10', containerId:'HLXU7748850', status:'Delivered', paid:true, paidAt:daysAgo(40), createdAt:daysAgo(75), updatedAt:daysAgo(28),
    items:[{desc:'Porcelain floor tile 60×60 matte grey',qty:1800,unit:'m²',cost:9.4,price:14.2},{desc:'Tile adhesive C2TE',qty:120,unit:'bag',cost:6.1,price:9.5}],
    history:hist([[75,'Order created'],[73,'Confirmed · split locked'],[70,'Marked as purchased'],[65,'In production'],[58,'Shipped'],[40,'Client payment received'],[34,'Arrived'],[28,'Delivered']]) },
  { id:'SO-1046', clientId:'c1', supplierId:'s2', priority:'Rush', requestedDate:'2026-10-25', containerId:'MSKU4471023', status:'Stuck', paid:true, paidAt:daysAgo(30), createdAt:daysAgo(55), updatedAt:daysAgo(9),
    items:[{desc:'Wall-hung toilet set w/ concealed cistern',qty:40,unit:'set',cost:112,price:168},{desc:'Rain shower column, brushed nickel',qty:40,unit:'pc',cost:58,price:89}],
    history:hist([[55,'Order created'],[54,'Confirmed · split locked'],[52,'Marked as purchased'],[48,'Shipped'],[30,'Client payment received'],[14,'Arrived'],[9,'Status set to Stuck — customs exam']]) },
  { id:'SO-1047', clientId:'c3', supplierId:'s2', priority:'Normal', requestedDate:'2026-11-01', containerId:'MSKU4471023', status:'Stuck', paid:false, createdAt:daysAgo(52), updatedAt:daysAgo(9),
    items:[{desc:'Vessel sink, white ceramic 50cm',qty:60,unit:'pc',cost:24,price:39}],
    history:hist([[52,'Order created'],[50,'Confirmed · split locked'],[49,'Marked as purchased'],[48,'Shipped'],[14,'Arrived'],[9,'Status set to Stuck — customs exam']]) },
  { id:'SO-1052', clientId:'c4', supplierId:'s3', priority:'Normal', requestedDate:'2026-09-30', containerId:'CMAU2203388', status:'Stuck', paid:true, paidAt:daysAgo(50), createdAt:daysAgo(95), updatedAt:daysAgo(3),
    items:[{desc:'Teak decking boards 19×90mm',qty:2400,unit:'lm',cost:7.8,price:12.4}],
    history:hist([[95,'Order created'],[94,'Confirmed · split locked'],[90,'Marked as purchased'],[62,'Shipped'],[50,'Client payment received'],[30,'Status set to Stuck — rolled at Panama']]) },
  { id:'SO-1058', clientId:'c1', supplierId:'s5', priority:'Normal', requestedDate:'2026-11-15', containerId:'TGHU8820916', status:'In Transit', paid:true, paidAt:daysAgo(10), createdAt:daysAgo(40), updatedAt:daysAgo(1),
    items:[{desc:'LED downlight 12W 4000K',qty:1200,unit:'pc',cost:3.2,price:5.1},{desc:'Interior door lever set, matte black',qty:150,unit:'set',cost:14.5,price:23}],
    history:hist([[40,'Order created'],[39,'Confirmed · split locked'],[36,'Marked as purchased'],[33,'Shipped'],[10,'Client payment received'],[1,'In transit — ETA Nov 8']]) },
  { id:'SO-1059', clientId:'c2', supplierId:'s5', priority:'Rush', requestedDate:'2026-11-12', containerId:'TGHU8820916', status:'In Transit', paid:false, createdAt:daysAgo(38), updatedAt:daysAgo(1),
    items:[{desc:'Kitchen cabinet hinges soft-close',qty:3000,unit:'pc',cost:0.9,price:1.6}],
    history:hist([[38,'Order created'],[37,'Confirmed · split locked'],[36,'Marked as purchased'],[33,'Shipped'],[1,'In transit — ETA Nov 8']]) },
  { id:'SO-1063', clientId:'c3', supplierId:'s4', priority:'Normal', requestedDate:'2026-11-28', containerId:'OOLU6619204', status:'Shipped', paid:true, paidAt:daysAgo(12), createdAt:daysAgo(30), updatedAt:daysAgo(7),
    items:[{desc:'Travertine slab 2cm honed',qty:320,unit:'m²',cost:38,price:61},{desc:'Marble mosaic sheet 30×30',qty:400,unit:'sheet',cost:6.5,price:11}],
    history:hist([[30,'Order created'],[28,'Confirmed · split locked'],[24,'Marked as purchased'],[12,'Client payment received'],[7,'Shipped']]) },
  { id:'SO-1067', clientId:'c1', supplierId:'s1', priority:'Normal', requestedDate:'2026-12-20', containerId:'MSKU3390117', status:'Purchased', paid:false, createdAt:daysAgo(12), updatedAt:daysAgo(4),
    items:[{desc:'Porcelain tile 120×60 wood-look',qty:2200,unit:'m²',cost:11.2,price:17}],
    history:hist([[12,'Order created'],[11,'Confirmed · split locked'],[4,'Marked as purchased']]) },
  { id:'SO-1068', clientId:'c2', supplierId:'s1', priority:'Rush', requestedDate:'2026-12-10', containerId:'MSKU3390117', status:'Confirmed', paid:false, createdAt:daysAgo(6), updatedAt:daysAgo(6),
    items:[{desc:'Mosaic pool tile glass blue',qty:600,unit:'m²',cost:18,price:29.5}],
    history:hist([[6,'Order created'],[6,'Confirmed · split locked']]) },
  { id:'SO-1069', clientId:'c4', supplierId:'s3', priority:'Normal', requestedDate:'2026-12-18', containerId:null, status:'Confirmed', paid:false, createdAt:daysAgo(5), updatedAt:daysAgo(5),
    items:[{desc:'Marine plywood 18mm BS1088',qty:400,unit:'sheet',cost:42,price:64},{desc:'Teak handrail profile',qty:180,unit:'lm',cost:15,price:24}],
    history:hist([[5,'Order created'],[5,'Confirmed · split locked']]) },
  { id:'SO-1070', clientId:'c3', supplierId:'s2', priority:'Normal', requestedDate:'2026-12-22', containerId:null, status:'Draft', paid:false, createdAt:daysAgo(1), updatedAt:daysAgo(1),
    items:[{desc:'Freestanding bathtub 170cm acrylic',qty:12,unit:'pc',cost:210,price:0}],
    history:hist([[1,'Order created']]) },
];

// Amount helpers
const orderTotals = (o) => {
  const total = o.items.reduce((s, i) => s + i.qty * i.price, 0);
  const supplier = o.items.reduce((s, i) => s + i.qty * i.cost, 0);
  return { total, supplier, margin: total - supplier };
};
// Lock split on confirm
ORDERS.forEach(o => { if (o.status !== 'Draft') { const t = orderTotals(o); o.split = { ...t, lockedAt: o.history[1]?.at || o.createdAt }; } else o.split = null; });

const seedState = () => ({ clients: CLIENTS, suppliers: SUPPLIERS, users: USERS, orders: JSON.parse(JSON.stringify(ORDERS)), containers: JSON.parse(JSON.stringify(CONTAINERS)) });

const fmt = (n) => '$' + Number(n).toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 });
const fmt0 = (n) => '$' + Math.round(Number(n)).toLocaleString('en-US');
const fdate = (s) => s ? new Date(s).toLocaleDateString('en-US', { month: 'short', day: 'numeric' }) : '—';
const fdateY = (s) => s ? new Date(s).toLocaleDateString('en-US', { month: 'short', day: 'numeric', year: 'numeric' }) : '—';
const daysSince = (s) => Math.floor((TODAY - new Date(s)) / 86400000);
const daysUntil = (s) => Math.ceil((new Date(s + 'T12:00:00') - TODAY) / 86400000);
const isPast = (s) => daysUntil(s) < 0;

const containerRisk = (c) => {
  if (c.status === 'Delivered') return null;
  if (c.status === 'Stuck') return { level: 'high', label: 'Stuck' };
  if (isPast(c.eta)) return { level: 'high', label: `${-daysUntil(c.eta)}d past ETA` };
  const stale = daysSince(c.updatedAt);
  if (stale >= 5) return { level: 'warn', label: `No update ${stale}d` };
  return null;
};
const orderOverdue = (o) => !CLOSED.includes(o.status) && o.status !== 'Draft' && isPast(o.requestedDate);
const orderValid = (o) => o.clientId && o.supplierId && o.requestedDate && o.items.length > 0 && o.items.every(i => i.desc && i.qty > 0 && i.unit && i.cost > 0 && i.price > 0);

const toCSV = (rows) => rows.map(r => r.map(v => `"${String(v ?? '').replace(/"/g, '""')}"`).join(',')).join('\n');
const download = (name, text) => { const a = document.createElement('a'); a.href = URL.createObjectURL(new Blob([text], { type: 'text/csv' })); a.download = name; a.click(); };

Object.assign(window, { TODAY, STATUSES, CLOSED, CONTAINER_STATUSES, seedState, orderTotals, fmt, fmt0, fdate, fdateY, daysSince, daysUntil, isPast, containerRisk, orderOverdue, orderValid, toCSV, download });
