/* ============ APP STORE + ROUTING ============ */
const {useState, useMemo, useCallback, useEffect, useRef} = React;

const ROUTE_META = {
  'dashboard':  {title:'Dashboard',        welcome:'Welcome back, Helbawi team 👋'},
  'items':      {title:'Items',            welcome:'Your full product catalogue'},
  'batches':    {title:'Batches',          welcome:'Track every batch and its expiry'},
  'stock-in':   {title:'Stock In',         welcome:'Receive new stock into the warehouse'},
  'stock-out':  {title:'Stock Out',        welcome:'Record items leaving the warehouse'},
  'scan':       {title:'Scan Barcode',     welcome:'Scan or weigh to update stock fast'},
  'movements':  {title:'Movement History', welcome:'Every stock movement, logged'},
  'low-stock':  {title:'Low Stock Alerts', welcome:'Items that need restocking'},
  'reports':    {title:'Reports',          welcome:'Stock, movement & expiry insights'},
};

const CAT_ABBR = {Spices:'SP',Dates:'DT',Nuts:'NT',Seeds:'SD','Dried Fruits':'DF',Coffee:'CF',Grains:'GR','Roasted & Mixed':'RM',Honey:'HN',Tea:'TE',Sweets:'SW','Helbawi Specials':'HL','Turkish Delight':'TD'};

function apiFetch(path, opts) {
  return fetch(path, opts).then(r => {
    if (!r.ok) return r.json().then(e => Promise.reject(new Error(e.error || r.statusText)));
    return r.json();
  });
}

function todayStr() { return new Date().toISOString().slice(0,10); }
function nowTime()  { const d=new Date(); return `${String(d.getHours()).padStart(2,'0')}:${String(d.getMinutes()).padStart(2,'0')}`; }

function App(){
  const [user,      setUser]      = useState(() => {
    try { return JSON.parse(localStorage.getItem('helbawi_user')) || null; } catch { return null; }
  });
  const [products,  setProducts]  = useState([]);
  const [movements, setMovements] = useState([]);
  const [loading,   setLoading]   = useState(true);
  const [route,     setRoute]     = useState('dashboard');
  const [search,    setSearch]    = useState('');
  const [showAdd,   setShowAdd]   = useState(false);
  const mvCounter = useRef(9000);

  const handleLogin  = (u) => { setUser(u); window.location.reload(); };
  const handleLogout = () => {
    localStorage.removeItem('helbawi_user');
    window.location.reload();
  };

  const isManager = user ? user.role === 'manager' : false;

  /* ── load ─────────────────────────────────────────────────────────── */
  useEffect(() => {
    if (!user) return; // don't load data if not logged in
    Promise.all([apiFetch('/api/meta'), apiFetch('/api/products'), apiFetch('/api/movements')])
      .then(([meta, prods, movs]) => {
        window.HELBAWI.today      = meta.today;
        window.HELBAWI.categories = meta.categories;
        const maxId = movs.reduce((m,x)=>Math.max(m, parseInt((x.id||'MV0000').replace('MV',''))||0), 0);
        mvCounter.current = Math.max(9000, maxId + 1);
        setProducts(prods);
        setMovements(movs);
        setLoading(false);
      })
      .catch(err => {
        toast({kind:'err', title:'Could not reach server', desc: err.message});
        setLoading(false);
      });
  }, [user]);

  const syncFromServer = useCallback(() => {
    Promise.all([apiFetch('/api/products'), apiFetch('/api/movements')])
      .then(([prods, movs]) => { setProducts(prods); setMovements(movs); })
      .catch(() => {});
  }, []);

  const lowCount = useMemo(()=>
    products.filter(p=>H.stockOf(p)>0 && ['Low','Critical'].includes(H.statusOf(p).key)).length,
  [products]);
  const expCount = useMemo(()=>
    products.filter(p=>{const e=H.nearestExpiry(p);return H.stockOf(p)>0&&e&&H.daysUntil(e)>=0&&H.daysUntil(e)<=35;}).length,
  [products]);
  const notifCount = lowCount + expCount;

  function mkMvId() {
    const id = 'MV' + String(mvCounter.current).padStart(4,'0');
    mvCounter.current++;
    return id;
  }
  function nextBatchCode(p) {
    const pre = 'B-'+(CAT_ABBR[p.category]||'GN');
    let max=0;
    products.forEach(pr=>pr.batches.forEach(b=>{const m=b.code.match(new RegExp('^'+pre.replace(/[-]/g,'\\-')+'(\\d+)$'));if(m)max=Math.max(max,+m[1]);}));
    return pre+String(max+1).padStart(3,'0');
  }

  /* ── STOCK IN — optimistic + background persist ───────────────────── */
  const stockIn = useCallback(({productId, qty, expiry}) => {
    const today=todayStr(), time=nowTime();
    let newMove=null, newProds=null;

    newProds = products.map(p => {
      if (p.id !== productId) return p;
      const batches = p.batches.map(b=>({...b}));
      const same = batches.find(b=>b.expiry===expiry);
      let code, isNew=false;
      if (same) { same.qty=Math.round((same.qty+qty)*10)/10; code=same.code; }
      else       { code=nextBatchCode(p); isNew=true; batches.push({code,addedOn:today,expiry,qty}); }
      batches.sort((a,b)=>a.expiry<b.expiry?-1:1);
      newMove = {id:mkMvId(),date:today,time,productId,product:p.nameEn,productAr:p.nameAr,
        type:isNew?'NEW_BATCH':'IN',qty,unit:p.unit,batchCode:code,expiry,employee:''};
      return {...p, batches};
    });

    setProducts(newProds);
    if (newMove) setMovements(prev => [newMove, ...prev]);

    apiFetch('/api/stock-in', {method:'POST',headers:{'Content-Type':'application/json'},
      body:JSON.stringify({productId,qty,expiry})})
      .then(() => syncFromServer())
      .catch(e => toast({kind:'err', title:'Save failed', desc:e.message}));
  }, [products, syncFromServer]);

  /* ── STOCK OUT — optimistic + background persist ──────────────────── */
  const stockOut = useCallback(({productId, qty, employee}) => {
    const prod = products.find(p=>p.id===productId);
    if (!prod) return false;
    const total = Math.round(prod.batches.reduce((s,b)=>s+b.qty,0)*10)/10;
    if (qty > total) return false;

    const today=todayStr(), time=nowTime();
    let firstCode=prod.batches[0]?.code, firstExp=prod.batches[0]?.expiry;
    const newMove = {id:mkMvId(),date:today,time,productId,product:prod.nameEn,productAr:prod.nameAr,
      type:'OUT',qty,unit:prod.unit,batchCode:firstCode,expiry:firstExp,employee};

    const newProds = products.map(p => {
      if (p.id !== productId) return p;
      let rem=qty;
      const batches = p.batches.map(b=>({...b})).sort((a,b)=>a.expiry<b.expiry?-1:1);
      for (const b of batches){ if(rem<=0)break; const take=Math.min(b.qty,rem); b.qty=Math.round((b.qty-take)*10)/10; rem=Math.round((rem-take)*10)/10; }
      return {...p, batches: batches.filter(b=>b.qty>0.001)};
    });

    setProducts(newProds);
    setMovements(prev => [newMove, ...prev]);

    apiFetch('/api/stock-out', {method:'POST',headers:{'Content-Type':'application/json'},
      body:JSON.stringify({productId,qty,employee})})
      .then(() => syncFromServer())
      .catch(e => toast({kind:'err', title:'Save failed', desc:e.message}));

    return true;
  }, [products, syncFromServer]);

  /* ── ADD PRODUCT ─────────────────────────────────────────────────── */
  const addProduct = useCallback((d) => {
    const today=todayStr(), tmpId=Date.now();
    const catAbbr=CAT_ABBR[d.category]||'GN';
    const code='F'+catAbbr+String(tmpId).slice(-6);
    const bCode='B-'+catAbbr+'001';
    const newP={id:tmpId,code,plu:d.plu||null,barcode:d.barcode||null,
      nameEn:d.nameEn,nameAr:d.nameAr||'',category:d.category,unit:d.unit,
      price:+d.price||0,threshold:+d.threshold||(d.unit==='kg'?8:5),
      batches:d.qty&&d.expiry?[{code:bCode,addedOn:today,expiry:d.expiry,qty:+d.qty}]:[]};
    setProducts(prev=>[...prev,newP]);
    if (d.qty&&d.expiry) setMovements(prev=>[{id:mkMvId(),date:today,time:nowTime(),
      productId:tmpId,product:d.nameEn,productAr:d.nameAr||'',type:'NEW_BATCH',
      qty:+d.qty,unit:d.unit,batchCode:bCode,expiry:d.expiry,employee:''},...prev]);

    apiFetch('/api/products',{method:'POST',headers:{'Content-Type':'application/json'},
      body:JSON.stringify({code,plu:d.plu||null,barcode:d.barcode||null,
        nameEn:d.nameEn,nameAr:d.nameAr||null,category:d.category,unit:d.unit,
        price:+d.price||0,threshold:+d.threshold||(d.unit==='kg'?8:5)})})
      .then(({id})=>{ if(d.qty&&d.expiry) return apiFetch('/api/stock-in',{method:'POST',
        headers:{'Content-Type':'application/json'},body:JSON.stringify({productId:id,qty:+d.qty,expiry:d.expiry})}); })
      .then(()=>syncFromServer())
      .catch(e=>toast({kind:'err',title:'Could not save product',desc:e.message}));
  }, [products, syncFromServer]);

  /* ── not logged in ───────────────────────────────────────────────── */
  if (!user) return window.LoginScreen ? <window.LoginScreen onLogin={handleLogin}/> : null;

  /* ── loading ──────────────────────────────────────────────────────── */
  if (loading) return (
    <div style={{display:'flex',alignItems:'center',justifyContent:'center',height:'100vh',flexDirection:'column',gap:16,background:'var(--page)'}}>
      <div style={{width:60,height:60,borderRadius:18,background:'var(--magenta)',display:'flex',alignItems:'center',justifyContent:'center'}}>
        <Icon name="box" size={30} style={{color:'#fff'}}/>
      </div>
      <div style={{fontWeight:800,fontSize:17,color:'var(--ink)'}}>Loading Helbawi Warehouse…</div>
    </div>
  );

  const meta = ROUTE_META[route]||ROUTE_META['dashboard'];
  const screenProps = {products,setProducts,movements,setRoute,route,search,stockIn,stockOut,addProduct};

  function renderScreen(){
    // Block reports for non-managers
    if (route === 'reports' && !isManager) return (
      <div className="content"><div className="card card-pad" style={{textAlign:'center',padding:'60px 30px'}}>
        <div style={{width:64,height:64,borderRadius:20,background:'var(--crit-bg)',display:'flex',alignItems:'center',justifyContent:'center',margin:'0 auto 16px'}}>
          <Icon name="alert" size={32} style={{color:'var(--crit)'}}/>
        </div>
        <div style={{fontSize:20,fontWeight:800,marginBottom:8}}>Manager Access Only</div>
        <div style={{color:'var(--muted)',fontSize:14}}>Reports are only available to managers.</div>
      </div></div>
    );
    switch(route){
      case 'dashboard': return <Dashboard {...screenProps}/>;
      case 'items':     return window.ItemsScreen     ? <window.ItemsScreen {...screenProps}/>     : <Stub name="Items"/>;
      case 'batches':   return window.BatchesScreen   ? <window.BatchesScreen {...screenProps}/>   : <Stub name="Batches"/>;
      case 'low-stock': return window.LowStockScreen  ? <window.LowStockScreen {...screenProps}/>  : <Stub name="Low Stock"/>;
      case 'stock-in':  return window.StockInScreen   ? <window.StockInScreen {...screenProps}/>   : <Stub name="Stock In"/>;
      case 'stock-out': return window.StockOutScreen  ? <window.StockOutScreen {...screenProps}/>  : <Stub name="Stock Out"/>;
      case 'scan':      return window.ScanScreen      ? <window.ScanScreen {...screenProps}/>      : <Stub name="Scan"/>;
      case 'movements': return window.MovementsScreen ? <window.MovementsScreen {...screenProps}/> : <Stub name="Movements"/>;
      case 'reports':   return window.ReportsScreen   ? <window.ReportsScreen {...screenProps}/>   : <Stub name="Reports"/>;
      default:          return <Dashboard {...screenProps}/>;
    }
  }

  return (
    <div className="app">
      <Sidebar route={route} setRoute={setRoute} products={products} lowCount={lowCount} isManager={isManager} user={user} onLogout={handleLogout}/>
      <main className="main">
        <Topbar title={meta.title} welcome={meta.welcome} search={search} setSearch={setSearch}
          notifCount={notifCount} onBell={()=>setRoute('low-stock')}
          onAdd={['items','batches','dashboard'].includes(route)?()=>setShowAdd(true):null}
          user={user} onLogout={handleLogout}/>
        {renderScreen()}
      </main>
      <MobileNav route={route} setRoute={setRoute} lowCount={lowCount} isManager={isManager}/>
      {showAdd&&window.AddProductModal&&<window.AddProductModal onClose={()=>setShowAdd(false)} addProduct={addProduct}/>}
      <ToastHost/>
    </div>
  );
}

function Stub({name}){
  return <div className="content"><div className="card card-pad"><div className="empty"><div style={{fontWeight:700}}>{name}</div><div>Loading…</div></div></div></div>;
}

ReactDOM.createRoot(document.getElementById('root')).render(<App/>);
