/* ═══════════════════════════════════════════════════════════
   TDL Buletine Portuare — React Frontend v2.0
   Loads via Babel standalone (no build step)
   ═══════════════════════════════════════════════════════════ */
const { useState, useEffect, useCallback, useRef } = React;
const {
  AreaChart, Area, BarChart, Bar, LineChart, Line, PieChart, Pie, Cell,
  XAxis, YAxis, CartesianGrid, Tooltip, Legend, ResponsiveContainer
} = Recharts;

// ─── Helpers ─────────────────────────────────────────────
const COLORS = ['#0ea5e9','#10b981','#f59e0b','#8b5cf6','#ef4444','#06b6d4','#ec4899','#14b8a6','#f97316','#6366f1','#a3e635','#fb7185'];
const fmt = v => new Intl.NumberFormat('ro-RO').format(Number(v||0));
const fmtDate = v => { if(!v) return '—'; const d=new Date(v); if(isNaN(d)) return String(v); const dd=String(d.getDate()).padStart(2,'0'), mm=String(d.getMonth()+1).padStart(2,'0'), yy=d.getFullYear(); return dd+'/'+mm+'/'+yy; };

function getToken() { return localStorage.getItem('bp_token'); }
function setToken(t) { t ? localStorage.setItem('bp_token',t) : localStorage.removeItem('bp_token'); }
function getUser() { try { return JSON.parse(localStorage.getItem('bp_user')); } catch{ return null; } }
function setUser(u) { u ? localStorage.setItem('bp_user',JSON.stringify(u)) : localStorage.removeItem('bp_user'); }

async function api(path, opts={}) {
  const headers = { 'Content-Type':'application/json' };
  const t = getToken();
  if(t) headers['Authorization'] = 'Bearer '+t;
  try {
    const r = await fetch('/api'+path, { ...opts, headers });
    if(r.status===401 && t) { setToken(null); setUser(null); window.location.reload(); return null; }
    if(r.status===401) return null;
    return r.json();
  } catch(e) { console.error('API error:', path, e); return null; }
}

// ─── Icons (SVG paths) ─────────────────────────────────
function Ico({d,s=18}) {
  return <svg width={s} height={s} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round"><path d={d}/></svg>;
}
const IC = {
  dash:"M3 9l9-7 9 7v11a2 2 0 01-2 2H5a2 2 0 01-2-2z M9 22V12h6v10",
  comm:"M12 2L2 7l10 5 10-5-10-5z M2 17l10 5 10-5 M2 12l10 5 10-5",
  ops:"M14.7 6.3a1 1 0 000 1.4l1.6 1.6a1 1 0 001.4 0l3.77-3.77a6 6 0 01-7.94 7.94l-6.91 6.91a2.12 2.12 0 01-3-3l6.91-6.91a6 6 0 017.94-7.94l-3.76 3.76z",
  fuel:"M17 3a2.83 2.83 0 114 4L7.5 20.5 2 22l1.5-5.5L17 3z",
  users:"M17 21v-2a4 4 0 00-4-4H5a4 4 0 00-4-4v2 M9 7a4 4 0 100-8 4 4 0 000 8z M23 21v-2a4 4 0 00-3-3.87 M16 3.13a4 4 0 010 7.75",
  gear:"M12 15a3 3 0 100-6 3 3 0 000 6z",
  out:"M9 21H5a2 2 0 01-2-2V5a2 2 0 012-2h4 M16 17l5-5-5-5 M21 12H9",
  exp:"M21 15v4a2 2 0 01-2 2H5a2 2 0 01-2-2v-4 M7 10l5 5 5-5 M12 15V3",
  filt:"M22 3H2l8 9.46V19l4 2v-8.54L22 3z",
  chk:"M20 6L9 17l-5-5",
  x:"M18 6L6 18 M6 6l12 12",
  db:"M12 2C6.48 2 2 4.02 2 6.5v11C2 19.98 6.48 22 12 22s10-2.02 10-4.5v-11C22 4.02 17.52 2 12 2z M2 6.5C2 8.98 6.48 11 12 11s10-2.02 10-4.5",
};

// ─── Tooltip style ──────────────────────────────────────
const ttStyle = { background:'#111827', border:'1px solid #1e293b', borderRadius:6, fontSize:12, color:'#e2e8f0' };
const ttItem = { color:'#e2e8f0' };
const ttLabel = { color:'#94a3b8', fontWeight:600, marginBottom:4 };

// ─── Export helpers ─────────────────────────────────────
function exportJSON(data, name) {
  const b = new Blob([JSON.stringify(data,null,2)],{type:'application/json'});
  const a = document.createElement('a'); a.href=URL.createObjectURL(b); a.download=name+'.json'; a.click();
}
function exportCSV(cols, rows, name) {
  const h = cols.map(c=>c.label).join(',');
  const body = rows.map(r=>cols.map(c=>`"${String(r[c.key]??'').replace(/"/g,'""')}"`).join(',')).join('\n');
  const b = new Blob(['\uFEFF'+h+'\n'+body],{type:'text/csv;charset=utf-8'});
  const a = document.createElement('a'); a.href=URL.createObjectURL(b); a.download=name+'.csv'; a.click();
}

// Reusable sort hook for any table
function useSortable(data) {
  const [sortKey,setSortKey]=useState(null);
  const [sortDir,setSortDir]=useState('asc');
  const onSort = (key) => {
    if(sortKey===key) setSortDir(sortDir==='asc'?'desc':'asc');
    else { setSortKey(key); setSortDir('asc'); }
  };
  const items = data||[];
  const sorted = sortKey ? [...items].sort((a,b)=>{
    let va=a[sortKey], vb=b[sortKey];
    if(va==null) va=''; if(vb==null) vb='';
    const na=Number(va), nb=Number(vb);
    if(!isNaN(na)&&!isNaN(nb)) return sortDir==='asc'?na-nb:nb-na;
    return sortDir==='asc'?String(va).localeCompare(String(vb)):String(vb).localeCompare(String(va));
  }) : items;
  const thProps = (key) => ({
    onClick:()=>onSort(key),
    style:{cursor:'pointer',userSelect:'none',whiteSpace:'nowrap'}
  });
  const arrow = (key) => sortKey===key?(sortDir==='asc'?' ▲':' ▼'):' ⇅';
  return { sorted, thProps, arrow, sortKey, sortDir };
}

// ═══════════════════════════════════════════════
// COMPONENTS
// ═══════════════════════════════════════════════

function Kpi({label,value,hint,color='#0ea5e9',trend}) {
  return <div className="kpi" style={{borderTopColor:color}}>
    <div className="kpi-label">{label}</div>
    <div className="kpi-value">{value}</div>
    <div className="kpi-hint">
      {trend!=null && <span style={{color:trend>=0?'#10b981':'#ef4444',fontWeight:600}}>{trend>=0?'+':''}{trend}%</span>}
      {' '}{hint}
    </div>
  </div>;
}

function DataTable({title,columns,rows,name}) {
  const [sortKey,setSortKey]=useState(null);
  const [sortDir,setSortDir]=useState('asc');
  
  const handleSort = (key) => {
    if(sortKey===key) setSortDir(sortDir==='asc'?'desc':'asc');
    else { setSortKey(key); setSortDir('asc'); }
  };
  
  const sorted = sortKey ? [...rows].sort((a,b)=>{
    let va=a[sortKey], vb=b[sortKey];
    if(va==null) va=''; if(vb==null) vb='';
    const na=Number(va), nb=Number(vb);
    if(!isNaN(na)&&!isNaN(nb)) return sortDir==='asc'?na-nb:nb-na;
    return sortDir==='asc'?String(va).localeCompare(String(vb)):String(vb).localeCompare(String(va));
  }) : rows;

  return <div className="card tbl-card">
    <div className="tbl-head">
      <span className="tbl-title">{title} <span className="tbl-count">({rows.length})</span></span>
      <div className="tbl-actions">
        <button className="btn-sm" onClick={()=>exportJSON(rows,name||title)}>JSON</button>
        <button className="btn-sm" onClick={()=>exportCSV(columns,rows,name||title)}>CSV</button>
      </div>
    </div>
    <div className="tbl-wrap">
      <table>
        <thead><tr>{columns.map((c,i)=><th key={i} onClick={()=>handleSort(c.key)} style={{cursor:'pointer',userSelect:'none',whiteSpace:'nowrap'}}>
          {c.label} {sortKey===c.key?(sortDir==='asc'?'▲':'▼'):'⇅'}
        </th>)}</tr></thead>
        <tbody>
          {sorted.length===0 && <tr><td colSpan={columns.length} className="empty">Fără date</td></tr>}
          {sorted.map((r,ri)=><tr key={ri}>{columns.map((c,ci)=><td key={ci}>{c.render?c.render(r[c.key],r):(r[c.key]??'—')}</td>)}</tr>)}
        </tbody>
      </table>
    </div>
  </div>;
}

function ChartCard({title,children,h=300}) {
  return <div className="card chart-card">
    <div className="chart-title">{title}</div>
    <div style={{height:h}}>{children}</div>
  </div>;
}

function Loading() { return <div className="loading">Se încarcă...</div>; }

// ═══════════════════════════════════════════════
// LOGIN PAGE
// ═══════════════════════════════════════════════
function LoginPage({onLogin}) {
  const [email,setEmail]=useState('');
  const [pass,setPass]=useState('');
  const [err,setErr]=useState('');
  const [loading,setLoading]=useState(false);

  const doLogin = async () => {
    if(!email||!pass) return setErr('Completează ambele câmpuri');
    setLoading(true); setErr('');
    try {
      const r = await fetch('/api/auth/login',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({email,password:pass})});
      const data = await r.json();
      if(!r.ok) { setErr(data.error||'Eroare'); setLoading(false); return; }
      setToken(data.token); setUser(data.user); onLogin(data.user);
    } catch(e) { setErr('Eroare conexiune server'); }
    setLoading(false);
  };

  return <div className="login-bg">
    <div className="login-box">
      <div className="login-brand">
        <img src="/logo.png" alt="Trading Line" className="login-logo"/>
        <div className="login-title">Buletine Portuare</div>
        <div className="login-sub">Intelligence Dashboard</div>
      </div>
      <div className="field">
        <label>Email</label>
        <input value={email} onChange={e=>{setEmail(e.target.value);setErr('');}} placeholder="email@tradingline.eu" onKeyDown={e=>e.key==='Enter'&&doLogin()}/>
      </div>
      <div className="field">
        <label>Parolă</label>
        <input type="password" value={pass} onChange={e=>setPass(e.target.value)} placeholder="••••••••" onKeyDown={e=>e.key==='Enter'&&doLogin()}/>
      </div>
      {err && <div className="login-err">{err}</div>}
      <button className="btn-primary" onClick={doLogin} disabled={loading}>{loading?'Se autentifică...':'Autentificare'}</button>
    </div>
  </div>;
}

// ═══════════════════════════════════════════════
// FILTER BAR
// ═══════════════════════════════════════════════
function Filters({f,set,snapshotDate}) {
  const s = (k,v)=>set({...f,[k]:v});
  const isCustom = f.mode === 'custom';
  const isDay = f.mode === 'day';

  // Navigate ±1 day
  const dayNav = (delta) => {
    const cur = f.date || snapshotDate || new Date().toISOString().slice(0,10);
    const d = new Date(cur);
    d.setDate(d.getDate() + delta);
    const iso = d.toISOString().slice(0,10);
    // Don't go past snapshot date
    if(snapshotDate && iso > snapshotDate && delta > 0) return;
    set({...f, mode:'day', date:iso});
  };

  const fmtEU = (iso) => {
    if(!iso) return '';
    const p = iso.split('-');
    return p.length===3 ? p[2]+'/'+p[1]+'/'+p[0] : iso;
  };

  return <div className="filters">
    <span className="filters-label"><Ico d={IC.filt} s={14}/> FILTRE</span>
    <select value={f.port||''} onChange={e=>set({...f,port:e.target.value})} style={{minWidth:110}} title="Port">
      <option value="">Toate porturile</option>
      <option value="constanta">Constanța</option>
      <option value="midia">Midia</option>
      <option value="mangalia">Mangalia</option>
    </select>
    <select value={isCustom?'custom':isDay?'day':f.days} onChange={e=>{
      const v = e.target.value;
      if(v==='custom') set({...f, mode:'custom'});
      else if(v==='day') set({...f, mode:'day', date:f.date||snapshotDate||''});
      else set({...f, mode:'days', days:v});
    }} style={{minWidth:100}}>
      <option value="day">O zi</option>
      <option value="7">7 zile</option><option value="14">14 zile</option>
      <option value="30">30 zile</option><option value="60">60 zile</option><option value="90">90 zile</option>
      <option value="custom">Custom...</option>
    </select>
    {isDay && <>
      <button className="btn-sm" onClick={()=>dayNav(-1)} title="Ziua anterioară" style={{fontSize:16,padding:'2px 8px'}}>◄</button>
      <input type="date" value={f.date||snapshotDate||''} onChange={e=>set({...f,mode:'day',date:e.target.value})} className="input-sm" style={{width:140}}/>
      <button className="btn-sm" onClick={()=>dayNav(1)} title="Ziua următoare" style={{fontSize:16,padding:'2px 8px'}} disabled={f.date>=snapshotDate}>►</button>
      <span style={{color:'#64748b',fontSize:11}}>{fmtEU(f.date||snapshotDate)}</span>
    </>}
    {isCustom && <>
      <input type="date" value={f.start||''} onChange={e=>s('start',e.target.value)} className="input-sm" style={{width:140}}/>
      <span style={{color:'#64748b'}}>→</span>
      <input type="date" value={f.end||''} onChange={e=>s('end',e.target.value)} className="input-sm" style={{width:140}}/>
      <span style={{color:'#64748b',fontSize:11}}>{fmtEU(f.start)} → {fmtEU(f.end)}</span>
    </>}
    <button className="btn-sm" onClick={()=>set({days:'30',mode:'day',date:snapshotDate||'',start:'',end:'',port:''})} title="Reset la ultima zi">Reset</button>
  </div>;
}

// Helper: build query string from filters
function fQ(f) {
  let qs = '';
  if(f.mode==='day' && f.date) qs = 'start='+f.date+'&end='+f.date;
  else if(f.mode==='custom' && f.start && f.end) qs = 'start='+f.start+'&end='+f.end;
  else qs = 'days='+f.days;
  if(f.port) qs += '&port='+f.port;
  return qs;
}
function periodLabel(f) {
  if(f.mode==='day') return fmtDate(f.date);
  if(f.mode==='custom'&&f.start) return fmtDate(f.start)+' → '+fmtDate(f.end);
  return f.days+' zile';
}

// ═══════════════════════════════════════════════
// DASHBOARD PAGE
// ═══════════════════════════════════════════════
function DashboardPage({f}) {
  const [snap,setSnap]=useState(null);
  const [trend,setTrend]=useState([]);
  const [agents,setAgents]=useState([]);
  const [cargo,setCargo]=useState([]);
  const [operators,setOps]=useState([]);

  useEffect(()=>{
    api('/snapshot?'+fQ(f)).then(setSnap);
    api('/trend?'+fQ(f)).then(d=>setTrend(d||[]));
    api('/top-agents?'+fQ(f)).then(d=>setAgents(d||[]));
    api('/top-cargo?'+fQ(f)).then(d=>setCargo(d||[]));
    api('/top-operators?'+fQ(f)).then(d=>setOps(d||[]));
  },[f.days,f.start,f.end,f.date,f.port]);

  if(!snap) return <Loading/>;
  const k = snap.kpis||{};
  const cv = snap.coverage||{};

  // Pivot trend data for chart
  const trendMap = {};
  (trend||[]).forEach(r => {
    const d = fmtDate(r.date);
    if(!trendMap[d]) trendMap[d]={date:d};
    trendMap[d][r.source]=Number(r.qty);
  });
  const trendData = Object.values(trendMap);

  return <div className="page-content">
    <div className="section-header">
      <h2>Dashboard</h2>
      <p>Snapshot {fmtDate(snap.snapshot_date)} · Coverage {fmtDate(cv.min_d)} → {fmtDate(cv.max_d)} · {fmt(cv.total)} importuri</p>
    </div>
    <div className="kpi-grid">
      <Kpi label="Fluvial sosiri" value={fmt(k.fl_sosiri)} hint={fmt(k.fl_sosiri_t)+' t avizate'} color="#0ea5e9"/>
      <Kpi label="Fluvial în port" value={fmt(k.fl_in_port)} hint={fmt(k.fl_rest_t)+' t rest'} color="#10b981"/>
      <Kpi label="Fluvial plecări" value={fmt(k.fl_plecari)} hint={fmt(k.fl_plecari_t)+' t'} color="#06b6d4"/>
      <Kpi label="Maritim sub operare" value={fmt(k.mt_sub_op)} hint={fmt(k.mt_rest_t)+' t rest'} color="#f59e0b"/>
      <Kpi label="Maritim în radă" value={fmt(k.mt_rada)} hint={fmt(k.mt_rada_t)+' t potențiale'} color="#8b5cf6"/>
      <Kpi label="Blocaje" value={fmt(k.mt_blocaje)} hint="fără operațiuni" color="#ef4444"/>
    </div>
    <div className="grid-2">
      <ChartCard title={"Trend tone/zi ("+periodLabel(f)+")"}>
        <ResponsiveContainer>
          <AreaChart data={trendData}>
            <CartesianGrid strokeDasharray="3 3" stroke="#1e293b"/>
            <XAxis dataKey="date" tick={{fill:'#64748b',fontSize:10}} angle={-20} textAnchor="end" height={40}/>
            <YAxis tick={{fill:'#64748b',fontSize:11}}/>
            <Tooltip contentStyle={ttStyle} itemStyle={ttItem} labelStyle={ttLabel} formatter={v=>fmt(v)+' t'}/>
            <Area type="monotone" dataKey="Fluvial sosiri" stroke="#0ea5e9" fill="#0ea5e9" fillOpacity={0.15}/>
            <Area type="monotone" dataKey="Maritim sub operare" stroke="#f59e0b" fill="#f59e0b" fillOpacity={0.15}/>
            <Area type="monotone" dataKey="Maritim radă" stroke="#8b5cf6" fill="#8b5cf6" fillOpacity={0.1}/>
            <Legend/>
          </AreaChart>
        </ResponsiveContainer>
      </ChartCard>
      <ChartCard title="Distribuție marfă (tone)">
        {cargo.length===0?<div className="empty">Nu sunt date marfă în perioada selectată</div>:
        <ResponsiveContainer>
          <PieChart>
            <Pie data={cargo.slice(0,10)} dataKey="qty" nameKey="marfa" cx="50%" cy="50%" innerRadius={45} outerRadius={95}
              label={({marfa,percent,x,y,cx})=>marfa&&percent>0.04?<text x={x} y={y} fill="#e2e8f0" fontSize={11} textAnchor={x>cx?'start':'end'} dominantBaseline="central">{marfa.substring(0,12)}</text>:null} labelLine={{stroke:'#64748b'}}>
              {cargo.slice(0,10).map((_,i)=><Cell key={i} fill={COLORS[i%COLORS.length]}/>)}
            </Pie>
            <Tooltip contentStyle={ttStyle} itemStyle={ttItem} labelStyle={ttLabel} formatter={v=>fmt(v)+' t'}/>
            <Legend wrapperStyle={{fontSize:10,color:'#94a3b8'}}/>
          </PieChart>
        </ResponsiveContainer>}
      </ChartCard>
    </div>
    <div className="grid-2">
      <ChartCard title="Top agenți (tone)">
        {agents.length===0?<div className="empty">Nu sunt date agenți pentru perioada selectată</div>:
        <ResponsiveContainer>
          <BarChart data={agents.slice(0,10)} layout="vertical">
            <CartesianGrid strokeDasharray="3 3" stroke="#1e293b"/>
            <XAxis type="number" tick={{fill:'#64748b',fontSize:11}}/>
            <YAxis dataKey="agent" type="category" width={85} tick={{fill:'#94a3b8',fontSize:10}}/>
            <Tooltip contentStyle={ttStyle} itemStyle={ttItem} labelStyle={ttLabel} formatter={v=>fmt(v)+' t'}/>
            <Bar dataKey="qty" fill="#0ea5e9" radius={[0,4,4,0]}/>
          </BarChart>
        </ResponsiveContainer>}
      </ChartCard>
      <ChartCard title="Top operatori portuari (tone)">
        {operators.length===0?<div className="empty">Nu sunt date pentru operatori în perioada selectată</div>:
        <ResponsiveContainer>
          <BarChart data={operators.slice(0,8)}>
            <CartesianGrid strokeDasharray="3 3" stroke="#1e293b"/>
            <XAxis dataKey="operator_name" tick={{fill:'#64748b',fontSize:9}} angle={-15} textAnchor="end" height={50}/>
            <YAxis tick={{fill:'#64748b',fontSize:11}}/>
            <Tooltip contentStyle={ttStyle} itemStyle={ttItem} labelStyle={ttLabel} formatter={v=>fmt(v)+' t'}/>
            <Bar dataKey="qty" fill="#10b981" radius={[4,4,0,0]}/>
          </BarChart>
        </ResponsiveContainer>}
      </ChartCard>
    </div>
  </div>;
}

// ═══════════════════════════════════════════════
// COMMERCIAL PAGE
// ═══════════════════════════════════════════════
function CommercialPage({f}) {
  const [routes,setRoutes]=useState([]);
  const [armatori,setArm]=useState([]);
  const [cargo,setCargo]=useState([]);

  useEffect(()=>{
    api('/routes?'+fQ(f)).then(d=>setRoutes(d||[]));
    api('/top-armatori?'+fQ(f)).then(d=>setArm(d||[]));
    api('/top-cargo?'+fQ(f)).then(d=>setCargo(d||[]));
  },[f.days,f.start,f.end,f.date,f.port]);

  return <div className="page-content">
    <div className="section-header">
      <h2>Commercial / Oportunități</h2>
      <p>Rute, armatori, leads din buletine — {periodLabel(f)}</p>
    </div>
    <div className="kpi-grid kpi-4">
      <Kpi label="Rute detectate" value={routes.length} hint="cu volum > 0" color="#0ea5e9"/>
      <Kpi label="Armatori activi" value={armatori.length} hint="din fl_af_sosire" color="#8b5cf6"/>
      <Kpi label="Tipuri marfă" value={cargo.length} hint="distincte" color="#10b981"/>
      <Kpi label="Volume totale" value={fmt(cargo.reduce((s,c)=>s+Number(c.qty||0),0))} hint="tone cumulate" color="#f59e0b"/>
    </div>
    <DataTable title="Rute comerciale" name="rute_comerciale" columns={[
      {key:'source',label:'Sursă'},{key:'provenienta',label:'Proveniență'},{key:'destinatie',label:'Destinație'},
      {key:'marfa',label:'Marfă'},{key:'unitati',label:'Unități'},{key:'qty',label:'Tone',render:v=>fmt(v)}
    ]} rows={routes}/>
    <div className="grid-2">
      <ChartCard title="Top armatori (tone)">
        {armatori.length===0?<div className="empty">Nu sunt date armatori pentru perioada selectată</div>:
        <ResponsiveContainer>
          <BarChart data={armatori.slice(0,10)} layout="vertical">
            <CartesianGrid strokeDasharray="3 3" stroke="#1e293b"/>
            <XAxis type="number" tick={{fill:'#64748b',fontSize:11}}/>
            <YAxis dataKey="armator" type="category" width={100} tick={{fill:'#94a3b8',fontSize:9}}/>
            <Tooltip contentStyle={ttStyle} itemStyle={ttItem} labelStyle={ttLabel} formatter={v=>fmt(v)+' t'}/>
            <Bar dataKey="qty" fill="#8b5cf6" radius={[0,4,4,0]}/>
          </BarChart>
        </ResponsiveContainer>}
      </ChartCard>
      <ChartCard title="Top marfă (tone)">
        {cargo.length===0?<div className="empty">Nu sunt date marfă pentru perioada selectată</div>:
        <ResponsiveContainer>
          <BarChart data={cargo.slice(0,10)}>
            <CartesianGrid strokeDasharray="3 3" stroke="#1e293b"/>
            <XAxis dataKey="marfa" tick={{fill:'#64748b',fontSize:9}} angle={-20} textAnchor="end" height={50}/>
            <YAxis tick={{fill:'#64748b',fontSize:11}}/>
            <Tooltip contentStyle={ttStyle} itemStyle={ttItem} labelStyle={ttLabel} formatter={v=>fmt(v)+' t'}/>
            <Bar dataKey="qty" fill="#0ea5e9" radius={[4,4,0,0]}/>
          </BarChart>
        </ResponsiveContainer>}
      </ChartCard>
    </div>
  </div>;
}

// ═══════════════════════════════════════════════
// OPERATIONS PAGE
// ═══════════════════════════════════════════════
function OpsPage({f}) {
  const [active,setActive]=useState([]);
  const [blockers,setBlock]=useState([]);
  const [backlog,setBack]=useState([]);

  useEffect(()=>{
    api('/ops-active?'+fQ(f)).then(d=>setActive(d||[]));
    api('/blockers?'+fQ(f)).then(d=>setBlock(d||[]));
    api('/backlog?'+fQ(f)).then(d=>setBack(d||[]));
  },[f.days,f.start,f.end,f.date,f.port]);

  return <div className="page-content">
    <div className="section-header">
      <h2>Operare</h2>
      <p>Nave active, rest de operat, blocaje — snapshot curent</p>
    </div>
    <div className="kpi-grid kpi-4">
      <Kpi label="Nave active" value={active.length} hint="cu rest > 0" color="#10b981"/>
      <Kpi label="Rest total" value={fmt(active.reduce((s,r)=>s+Number(r.rest||0),0))} hint="tone" color="#0ea5e9"/>
      <Kpi label="Blocaje" value={blockers.length} hint="fără operațiuni" color="#ef4444"/>
      <Kpi label="Locații" value={backlog.length} hint="dane/zone active" color="#f59e0b"/>
    </div>
    <DataTable title="Nave / convoaie cu rest de operat" name="ops_active" columns={[
      {key:'mode',label:'Mod',render:v=><span className={'badge '+(v==='Fluvial'?'badge-blue':'badge-amber')}>{v}</span>},
      {key:'zona',label:'Zona'},{key:'loc',label:'Dana'},{key:'nava',label:'Navă'},
      {key:'agent',label:'Agent'},{key:'marfa',label:'Marfă'},
      {key:'rest',label:'Rest (t)',render:v=><strong>{fmt(v)}</strong>},{key:'operator',label:'Operator'}
    ]} rows={active}/>
    <div className="grid-2">
      <DataTable title="Blocaje maritime" name="blocaje" columns={[
        {key:'zona',label:'Zona'},{key:'dana',label:'Dana'},{key:'nava',label:'Navă'},
        {key:'motiv',label:'Motiv',render:v=><span style={{color:'#f59e0b'}}>{v}</span>},{key:'agent',label:'Agent'}
      ]} rows={blockers}/>
      <DataTable title="Backlog pe locații" name="backlog" columns={[
        {key:'mode',label:'Mod'},{key:'zona',label:'Zona'},{key:'loc',label:'Loc'},
        {key:'unitati',label:'Unități'},{key:'rest',label:'Rest (t)',render:v=>fmt(v)}
      ]} rows={backlog}/>
    </div>
  </div>;
}

// ═══════════════════════════════════════════════
// BUNKER / COMBUSTIBILI PAGE
// ═══════════════════════════════════════════════
function BunkerPage({f}) {
  const [data,setData]=useState(null);
  const sortMt = useSortable(data?.maritime||[]);
  const sortFl = useSortable(data?.fluvial||[]);
  useEffect(()=>{ api('/lichide?'+fQ(f)).then(d=>setData(d)); },[f.days,f.start,f.end,f.date,f.port]);
  if(!data) return <Loading/>;

  const all = [...(data.maritime||[]), ...(data.fluvial||[])];
  const byDest = {};
  all.forEach(r=>{ const k=r.destinatie||r.operator||'N/A'; byDest[k]=(byDest[k]||0)+Number(r.cantitate_tone||0); });
  const destChart = Object.entries(byDest).map(([k,v])=>({dest:k,qty:v})).sort((a,b)=>b.qty-a.qty);

  return <div className="page-content">
    <div className="section-header">
      <h2>Lichide / Bunker</h2>
      <p>Motorină, benzină, benzen, ulei — maritime + fluviale, {periodLabel(f)}</p>
    </div>
    <div className="kpi-grid kpi-4">
      <Kpi label="Maritime" value={data.maritime?.length||0} hint="operațiuni lichide" color="#ef4444"/>
      <Kpi label="Fluviale" value={data.fluvial?.length||0} hint="transporturi lichide" color="#f59e0b"/>
      <Kpi label="Volum total" value={fmt(data.total_tone||0)} hint="tone" color="#8b5cf6"/>
      <Kpi label="Destinații" value={data.destinatii?.length||0} hint="porturi" color="#0ea5e9"/>
    </div>
    {destChart.length>0 && <ChartCard title="Volum lichide per destinație/operator">
      <ResponsiveContainer>
        <BarChart data={destChart.slice(0,10)}>
          <CartesianGrid strokeDasharray="3 3" stroke="#1e293b"/>
          <XAxis dataKey="dest" tick={{fill:'#64748b',fontSize:10}} angle={-15} textAnchor="end" height={50}/>
          <YAxis tick={{fill:'#64748b',fontSize:11}}/>
          <Tooltip contentStyle={ttStyle} itemStyle={ttItem} labelStyle={ttLabel} formatter={v=>fmt(v)+' t'}/>
          <Bar dataKey="qty" fill="#ef4444" radius={[4,4,0,0]}/>
        </BarChart>
      </ResponsiveContainer>
    </ChartCard>}
    <div className="card tbl-card">
      <div className="tbl-head"><span className="tbl-title">Maritime — nave tank sub operare ({data.maritime?.length||0})</span></div>
      <div className="tbl-wrap"><table>
        <thead><tr>
          <th {...sortMt.thProps('data_buletin')}>Data{sortMt.arrow('data_buletin')}</th>
          <th {...sortMt.thProps('nava')}>Navă{sortMt.arrow('nava')}</th>
          <th {...sortMt.thProps('agent')}>Agent{sortMt.arrow('agent')}</th>
          <th {...sortMt.thProps('armator_master')}>Armator{sortMt.arrow('armator_master')}</th>
          <th {...sortMt.thProps('marfa')}>Marfă{sortMt.arrow('marfa')}</th>
          <th {...sortMt.thProps('cantitate_tone')}>Tone{sortMt.arrow('cantitate_tone')}</th>
          <th {...sortMt.thProps('cantitate_operata')}>Operat{sortMt.arrow('cantitate_operata')}</th>
          <th {...sortMt.thProps('cantitate_rest')}>Rest{sortMt.arrow('cantitate_rest')}</th>
          <th {...sortMt.thProps('operator')}>Operator{sortMt.arrow('operator')}</th>
        </tr></thead>
        <tbody>{sortMt.sorted.slice(0,50).map((r,i)=><tr key={i}>
          <td>{fmtDate(r.data_buletin)}</td>
          <td style={{fontWeight:600,color:'#e2e8f0'}}>{r.nava||'—'}</td>
          <td>{r.agent||'—'}</td>
          <td style={{fontSize:11}}>{r.armator_master||'—'}</td>
          <td>{r.marfa||'—'}</td>
          <td>{fmt(r.cantitate_tone)}</td>
          <td>{fmt(r.cantitate_operata)}</td>
          <td>{fmt(r.cantitate_rest)}</td>
          <td style={{fontSize:11}}>{r.operator||'—'}</td>
        </tr>)}</tbody>
      </table></div>
    </div>
    <div className="card tbl-card" style={{marginTop:16}}>
      <div className="tbl-head"><span className="tbl-title">Fluvial — convoaie combustibili ({data.fluvial?.length||0})</span></div>
      <div className="tbl-wrap"><table>
        <thead><tr>
          <th {...sortFl.thProps('data_buletin')}>Data{sortFl.arrow('data_buletin')}</th>
          <th {...sortFl.thProps('nava')}>Navă/Convoi{sortFl.arrow('nava')}</th>
          <th {...sortFl.thProps('armator')}>Armator{sortFl.arrow('armator')}</th>
          <th {...sortFl.thProps('marfa')}>Marfă{sortFl.arrow('marfa')}</th>
          <th {...sortFl.thProps('cantitate_tone')}>Tone{sortFl.arrow('cantitate_tone')}</th>
          <th {...sortFl.thProps('provenienta')}>Proveniență{sortFl.arrow('provenienta')}</th>
          <th {...sortFl.thProps('destinatie')}>Destinație{sortFl.arrow('destinatie')}</th>
        </tr></thead>
        <tbody>{sortFl.sorted.slice(0,50).map((r,i)=><tr key={i}>
          <td>{fmtDate(r.data_buletin)}</td>
          <td style={{fontWeight:600,color:'#e2e8f0'}}>{r.nava||'—'}</td>
          <td style={{fontSize:11}}>{r.armator||'—'}</td>
          <td>{r.marfa||'—'}</td>
          <td>{fmt(r.cantitate_tone)}</td>
          <td>{r.provenienta||'—'}</td>
          <td>{r.destinatie||'—'}</td>
        </tr>)}</tbody>
      </table></div>
    </div>
  </div>;
}

// ═══════════════════════════════════════════════
// CONFIG — USERS
// ═══════════════════════════════════════════════
function UsersPage() {
  const [users,setUsers]=useState([]);
  const [showAdd,setShowAdd]=useState(false);
  const [editing,setEditing]=useState(null);
  const [form,setForm]=useState({name:'',email:'',password:'',role:'operations'});
  const ROLES = {ceo:'CEO',commercial:'Commercial',operations:'Operare',admin:'Admin'};

  const load = ()=>api('/users').then(d=>setUsers(d||[]));
  useEffect(load,[]);

  const addUser = async()=>{
    if(!form.name||!form.email||!form.password) return alert('Completează toate câmpurile');
    await api('/users',{method:'POST',body:JSON.stringify(form)});
    setShowAdd(false); setForm({name:'',email:'',password:'',role:'operations'}); load();
  };

  const saveEdit = async()=>{
    if(!editing) return;
    const body = {name:editing.name, email:editing.email, role:editing.role, active:editing.active};
    if(editing.newPassword) body.password = editing.newPassword;
    await api('/users/'+editing.id,{method:'PUT',body:JSON.stringify(body)});
    setEditing(null); load();
  };

  const deleteUser = async(u)=>{
    if(!confirm(`Șterge definitiv userul "${u.name}" (${u.email})?`)) return;
    await api('/users/'+u.id,{method:'DELETE'});
    load();
  };

  const toggle = async(u)=>{
    await api('/users/'+u.id,{method:'PUT',body:JSON.stringify({...u,active:!u.active})});
    load();
  };

  const inputStyle = {width:'100%',padding:'8px 12px',background:'#0f172a',border:'1px solid #334155',borderRadius:6,color:'#e2e8f0',fontSize:13};

  return <div className="page-content">
    <div className="section-header" style={{display:'flex',justifyContent:'space-between',alignItems:'flex-start'}}>
      <div><h2>Utilizatori</h2><p>Gestionare conturi, roluri și parole</p></div>
      <button className="btn-primary" onClick={()=>{setShowAdd(!showAdd);setEditing(null);}}>{showAdd?'Anulează':'+ Utilizator nou'}</button>
    </div>

    {/* Add new user form */}
    {showAdd && <div className="card" style={{padding:20,display:'flex',gap:12,flexWrap:'wrap',alignItems:'flex-end'}}>
      <div className="field"><label>Nume</label><input style={inputStyle} value={form.name} onChange={e=>setForm({...form,name:e.target.value})} placeholder="Nume complet"/></div>
      <div className="field"><label>Email</label><input style={inputStyle} value={form.email} onChange={e=>setForm({...form,email:e.target.value})} placeholder="email@tradingline.eu"/></div>
      <div className="field"><label>Parolă</label><input style={inputStyle} type="password" value={form.password} onChange={e=>setForm({...form,password:e.target.value})} placeholder="parolă"/></div>
      <div className="field"><label>Rol</label><select style={inputStyle} value={form.role} onChange={e=>setForm({...form,role:e.target.value})}>
        {Object.entries(ROLES).map(([k,v])=><option key={k} value={k}>{v}</option>)}
      </select></div>
      <button className="btn-primary" onClick={addUser}>Salvează</button>
    </div>}

    {/* Edit user modal */}
    {editing && <div className="card" style={{padding:20,marginBottom:16,border:'1px solid #0ea5e9'}}>
      <div style={{display:'flex',justifyContent:'space-between',alignItems:'center',marginBottom:16}}>
        <h3 style={{margin:0,color:'#0ea5e9'}}>Editare: {editing.name}</h3>
        <button className="btn-sm" onClick={()=>setEditing(null)}>✕ Închide</button>
      </div>
      <div style={{display:'grid',gridTemplateColumns:'repeat(auto-fit,minmax(200px,1fr))',gap:16}}>
        <div><label style={{display:'block',fontSize:11,color:'#94a3b8',marginBottom:4}}>Nume</label>
          <input style={inputStyle} value={editing.name} onChange={e=>setEditing({...editing,name:e.target.value})}/></div>
        <div><label style={{display:'block',fontSize:11,color:'#94a3b8',marginBottom:4}}>Email</label>
          <input style={inputStyle} value={editing.email} onChange={e=>setEditing({...editing,email:e.target.value})}/></div>
        <div><label style={{display:'block',fontSize:11,color:'#94a3b8',marginBottom:4}}>Rol</label>
          <select style={inputStyle} value={editing.role} onChange={e=>setEditing({...editing,role:e.target.value})}>
            {Object.entries(ROLES).map(([k,v])=><option key={k} value={k}>{v}</option>)}
          </select></div>
        <div><label style={{display:'block',fontSize:11,color:'#94a3b8',marginBottom:4}}>Parolă nouă <span style={{color:'#64748b'}}>(gol = neschimbată)</span></label>
          <input style={inputStyle} type="password" value={editing.newPassword||''} onChange={e=>setEditing({...editing,newPassword:e.target.value})} placeholder="lasă gol pentru a nu schimba"/></div>
      </div>
      <div style={{marginTop:16,display:'flex',gap:8}}>
        <button className="btn-primary" onClick={saveEdit}>💾 Salvează modificările</button>
        <button className="btn-sm" onClick={()=>setEditing(null)}>Anulează</button>
      </div>
    </div>}

    {/* Users table */}
    <div className="card tbl-card">
      <div className="tbl-wrap">
        <table>
          <thead><tr><th>ID</th><th>Nume</th><th>Email</th><th>Rol</th><th>Status</th><th>Ultimul login</th><th>Acțiuni</th></tr></thead>
          <tbody>{users.map(u=><tr key={u.id} style={editing?.id===u.id?{background:'rgba(14,165,233,.1)'}:{}}>
            <td style={{color:'#64748b',fontSize:11}}>{u.id}</td>
            <td style={{fontWeight:500,color:'#e2e8f0'}}>{u.name}</td>
            <td style={{fontSize:12}}>{u.email}</td>
            <td><span className={'badge badge-'+(u.role==='ceo'?'purple':u.role==='commercial'?'blue':'green')}>{ROLES[u.role]||u.role}</span></td>
            <td><span className={'dot '+(u.active?'dot-green':'dot-red')}/>{u.active?'Activ':'Inactiv'}</td>
            <td style={{fontSize:11}}>{fmtDate(u.last_login)}</td>
            <td style={{whiteSpace:'nowrap'}}>
              <button className="btn-sm" onClick={()=>{setEditing({...u,newPassword:''});setShowAdd(false);}} title="Editează" style={{marginRight:4}}>✏️</button>
              <button className="btn-sm" onClick={()=>toggle(u)} title={u.active?'Dezactivează':'Activează'} style={{marginRight:4}}>{u.active?'🔒':'🔓'}</button>
              <button className="btn-sm" onClick={()=>deleteUser(u)} title="Șterge" style={{color:'#ef4444'}}>🗑️</button>
            </td>
          </tr>)}</tbody>
        </table>
      </div>
    </div>
  </div>;
}

// ═══════════════════════════════════════════════
// CONFIG — SETTINGS
// ═══════════════════════════════════════════════
function SettingsPage() {
  const [db,setDb]=useState(null);
  const [dq,setDq]=useState(null);
  const [tab,setTab]=useState('agents');
  const [agents,setAgents]=useState([]);
  const [operators,setOps]=useState([]);
  const [marfa,setMarfa]=useState([]);
  const [editAgent,setEA]=useState(null);
  const [editOp,setEO]=useState(null);
  const [editMarfa,setEM]=useState(null);
  const [searchA,setSearchA]=useState('');
  const [searchO,setSearchO]=useState('');
  const [searchM,setSearchM]=useState('');

  const loadAgents = ()=>api('/agent-codes').then(d=>setAgents(d||[]));
  const loadOps = ()=>api('/operator-codes').then(d=>setOps(d||[]));
  const loadMarfa = ()=>api('/marfa-master').then(d=>setMarfa(d||[]));
  useEffect(()=>{ api('/system/db-status').then(setDb); api('/data-quality').then(setDq); loadAgents(); loadOps(); loadMarfa(); },[]);

  const saveAgent = async (data) => {
    if(data.id) await api('/agent-codes/'+data.id,{method:'PUT',headers:{'Content-Type':'application/json'},body:JSON.stringify(data)});
    else await api('/agent-codes',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify(data)});
    setEA(null); loadAgents();
  };
  const delAgent = async (id) => { if(confirm('Șterge agentul?')){ await api('/agent-codes/'+id,{method:'DELETE'}); loadAgents(); }};

  const saveOp = async (data) => {
    if(data.id) await api('/operator-codes/'+data.id,{method:'PUT',headers:{'Content-Type':'application/json'},body:JSON.stringify(data)});
    else await api('/operator-codes',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify(data)});
    setEO(null); loadOps();
  };
  const delOp = async (id) => { if(confirm('Șterge operatorul?')){ await api('/operator-codes/'+id,{method:'DELETE'}); loadOps(); }};

  const saveMarfaItem = async (data) => {
    if(data.id) await api('/marfa-master/'+data.id,{method:'PUT',headers:{'Content-Type':'application/json'},body:JSON.stringify(data)});
    else await api('/marfa-master',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify(data)});
    setEM(null); loadMarfa();
  };
  const delMarfa = async (id) => { if(confirm('Șterge marfa?')){ await api('/marfa-master/'+id,{method:'DELETE'}); loadMarfa(); }};

  const CodeForm = ({item,onSave,onCancel,fields,title}) => {
    const [data,setData]=useState(item||{});
    return <div className="card" style={{padding:16,marginBottom:16,borderLeft:'3px solid #0ea5e9'}}>
      <div style={{fontSize:13,fontWeight:600,color:'#e2e8f0',marginBottom:10}}>{title||'Editare'}</div>
      <div style={{display:'grid',gridTemplateColumns:'repeat(auto-fill,minmax(200px,1fr))',gap:8}}>
        {fields.map(f=><div key={f.key}>
          <label style={{fontSize:10,color:'#64748b',display:'block',marginBottom:2}}>{f.label}</label>
          {f.type==='select' ? <select value={data[f.key]||f.def||''} onChange={e=>setData({...data,[f.key]:e.target.value})} style={{width:'100%',padding:6,background:'#0f172a',color:'#e2e8f0',border:'1px solid #334155',borderRadius:4,fontSize:12}}>
            {f.options.map(o=><option key={o} value={o}>{o}</option>)}
          </select> :
          f.type==='textarea' ? <textarea value={data[f.key]||''} onChange={e=>setData({...data,[f.key]:e.target.value})} placeholder={f.hint||''} rows={2} style={{width:'100%',padding:6,background:'#0f172a',color:'#e2e8f0',border:'1px solid #334155',borderRadius:4,fontSize:12,resize:'vertical'}}/> :
          <input value={data[f.key]||''} onChange={e=>setData({...data,[f.key]:e.target.value})} placeholder={f.hint||''} style={{width:'100%',padding:6,background:'#0f172a',color:'#e2e8f0',border:'1px solid #334155',borderRadius:4,fontSize:12}}/>}
        </div>)}
      </div>
      <div style={{marginTop:10,display:'flex',gap:8}}>
        <button className="btn-primary" onClick={()=>onSave(data)}>{data.id?'Actualizează':'Adaugă'}</button>
        <button className="btn-sm" onClick={onCancel}>Anulează</button>
      </div>
    </div>;
  };

  const SearchBox = ({value,onChange,placeholder}) => <input value={value} onChange={e=>onChange(e.target.value)} 
    placeholder={placeholder||'Caută...'} style={{padding:'6px 10px',background:'#0f172a',color:'#e2e8f0',border:'1px solid #334155',borderRadius:4,fontSize:12,width:250}}/>;

  const filtA = agents.filter(a=>{const s=searchA.toLowerCase(); return !s||a.cod?.toLowerCase().includes(s)||a.nume_complet?.toLowerCase().includes(s)||a.email?.toLowerCase().includes(s);});
  const filtO = operators.filter(o=>{const s=searchO.toLowerCase(); return !s||o.cod?.toLowerCase().includes(s)||o.nume_complet?.toLowerCase().includes(s)||o.locatie?.toLowerCase().includes(s);});
  const filtM = marfa.filter(m=>{const s=searchM.toLowerCase(); return !s||m.cod?.toLowerCase().includes(s)||m.nume_ro?.toLowerCase().includes(s)||m.categorie?.toLowerCase().includes(s)||m.search_patterns?.toLowerCase().includes(s);});
  const sA = useSortable(filtA);
  const sO = useSortable(filtO);
  const sM = useSortable(filtM);

  return <div className="page-content">
    <div className="section-header"><h2>Setări & Master Tables</h2><p>Gestionare agenți, operatori, marfă, nave, status DB și calitate date</p></div>
    <div style={{display:'flex',gap:6,marginBottom:16,flexWrap:'wrap'}}>
      {[['agents','Agenți Portuari',agents.length],['operators','Operatori Portuari',operators.length],['marfa','Marfă Master',marfa.length],['navemaster','Nave Master','26K+'],['quality','Calitate Date','FK'],['db','Status DB','']].map(([id,label,cnt])=>
        <button key={id} onClick={()=>setTab(id)} className={tab===id?'btn-primary':'btn-sm'}>{label}{cnt?' ('+cnt+')':''}</button>
      )}
    </div>

    {tab==='agents'&&<div>
      <div style={{display:'flex',justifyContent:'space-between',marginBottom:12,alignItems:'center',flexWrap:'wrap',gap:8}}>
        <SearchBox value={searchA} onChange={setSearchA} placeholder="Caută agent (cod, nume, email)..."/>
        <div><span style={{color:'#94a3b8',fontSize:12,marginRight:8}}>agenti_master · {filtA.length}/{agents.length} agenți</span>
        <button className="btn-primary" onClick={()=>setEA({})}>+ Agent nou</button></div>
      </div>
      {editAgent&&<CodeForm item={editAgent} onSave={saveAgent} onCancel={()=>setEA(null)} title={editAgent.id?'Editare agent: '+editAgent.cod:'Agent nou'} fields={[
        {key:'cod',label:'Cod (2-6 litere)',hint:'ARI'},
        {key:'nume_complet',label:'Nume complet',hint:'Aris Ship Management SRL'},
        {key:'tip',label:'Tip',type:'select',options:['fluvial','maritim','ambele'],def:'ambele'},
        {key:'telefon',label:'Telefon',hint:'+40...'},{key:'email',label:'Email',hint:'office@...'},
        {key:'observatii',label:'Observații',type:'textarea'}
      ]}/>}
      <div className="card tbl-card"><div className="tbl-wrap"><table>
        <thead><tr>
          <th {...sA.thProps('cod')}>Cod{sA.arrow('cod')}</th>
          <th {...sA.thProps('nume_complet')}>Nume complet{sA.arrow('nume_complet')}</th>
          <th {...sA.thProps('tip')}>Tip{sA.arrow('tip')}</th>
          <th {...sA.thProps('nr_aparitii')}>Apariții{sA.arrow('nr_aparitii')}</th>
          <th {...sA.thProps('ultima_aparitie')}>Ultima{sA.arrow('ultima_aparitie')}</th>
          <th>Telefon</th><th>Email</th><th>Acțiuni</th>
        </tr></thead>
        <tbody>{sA.sorted.length===0&&<tr><td colSpan={8} className="empty">Niciun agent găsit</td></tr>}
        {sA.sorted.map(a=><tr key={a.id}>
          <td><span className="mono" style={{color:'#0ea5e9',fontWeight:700}}>{a.cod}</span></td>
          <td>{a.nume_complet||'—'}</td><td><span className="badge badge-blue">{a.tip||'—'}</span></td>
          <td style={{fontSize:11,textAlign:'center'}}>{a.nr_aparitii||0}</td>
          <td style={{fontSize:11}}>{fmtDate(a.ultima_aparitie)||'—'}</td>
          <td style={{fontSize:11}}>{a.telefon||'—'}</td><td style={{fontSize:11}}>{a.email||'—'}</td>
          <td><button className="btn-sm" onClick={()=>setEA(a)} style={{marginRight:4}}>✏️</button>
            <button className="btn-sm" onClick={()=>delAgent(a.id)} style={{color:'#ef4444'}}>🗑️</button></td>
        </tr>)}</tbody>
      </table></div></div>
    </div>}

    {tab==='operators'&&<div>
      <div style={{display:'flex',justifyContent:'space-between',marginBottom:12,alignItems:'center',flexWrap:'wrap',gap:8}}>
        <SearchBox value={searchO} onChange={setSearchO} placeholder="Caută operator (cod, nume, locație)..."/>
        <div><span style={{color:'#94a3b8',fontSize:12,marginRight:8}}>operatori_master · {filtO.length}/{operators.length}</span>
        <button className="btn-primary" onClick={()=>setEO({})}>+ Operator nou</button></div>
      </div>
      {editOp&&<CodeForm item={editOp} onSave={saveOp} onCancel={()=>setEO(null)} title={editOp.id?'Editare operator: '+editOp.cod:'Operator nou'} fields={[
        {key:'cod',label:'Cod',hint:'COMVEX'},
        {key:'nume_complet',label:'Nume complet',hint:'Comvex SA'},
        {key:'tip',label:'Tip',type:'select',options:['port','terminal','transport','altul'],def:'port'},
        {key:'locatie',label:'Locație',hint:'Constanta Sud'},
        {key:'zona',label:'Zonă',hint:'Constanta'},
        {key:'telefon',label:'Telefon'},{key:'email',label:'Email'},{key:'observatii',label:'Observații',type:'textarea'}
      ]}/>}
      <div className="card tbl-card"><div className="tbl-wrap"><table>
        <thead><tr>
          <th {...sO.thProps('cod')}>Cod{sO.arrow('cod')}</th>
          <th {...sO.thProps('nume_complet')}>Nume complet{sO.arrow('nume_complet')}</th>
          <th {...sO.thProps('tip')}>Tip{sO.arrow('tip')}</th>
          <th {...sO.thProps('locatie')}>Locație{sO.arrow('locatie')}</th>
          <th {...sO.thProps('zona')}>Zonă{sO.arrow('zona')}</th>
          <th {...sO.thProps('nr_aparitii')}>Apariții{sO.arrow('nr_aparitii')}</th>
          <th>Acțiuni</th>
        </tr></thead>
        <tbody>{sO.sorted.length===0&&<tr><td colSpan={7} className="empty">Niciun operator găsit</td></tr>}
        {sO.sorted.map(o=><tr key={o.id}>
          <td><span className="mono" style={{color:'#10b981',fontWeight:700}}>{o.cod}</span></td>
          <td>{o.nume_complet||'—'}</td><td><span className="badge badge-green">{o.tip||'—'}</span></td>
          <td style={{fontSize:11}}>{o.locatie||'—'}</td><td style={{fontSize:11}}>{o.zona||'—'}</td>
          <td style={{fontSize:11,textAlign:'center'}}>{o.nr_aparitii||0}</td>
          <td><button className="btn-sm" onClick={()=>setEO(o)} style={{marginRight:4}}>✏️</button>
            <button className="btn-sm" onClick={()=>delOp(o.id)} style={{color:'#ef4444'}}>🗑️</button></td>
        </tr>)}</tbody>
      </table></div></div>
    </div>}

    {tab==='marfa'&&<div>
      <div style={{display:'flex',justifyContent:'space-between',marginBottom:12,alignItems:'center',flexWrap:'wrap',gap:8}}>
        <SearchBox value={searchM} onChange={setSearchM} placeholder="Caută marfă (cod, nume, categorie, pattern)..."/>
        <div><span style={{color:'#94a3b8',fontSize:12,marginRight:8}}>marfa_master · {filtM.length}/{marfa.length}</span>
        <button className="btn-primary" onClick={()=>setEM({})}>+ Marfă nouă</button></div>
      </div>
      {editMarfa&&<CodeForm item={editMarfa} onSave={saveMarfaItem} onCancel={()=>setEM(null)} title={editMarfa.id?'Editare marfă: '+editMarfa.cod:'Marfă nouă'} fields={[
        {key:'cod',label:'Cod unic',hint:'WHEAT'},
        {key:'nume_ro',label:'Nume RO',hint:'Grâu'},
        {key:'nume_en',label:'Nume EN',hint:'Wheat'},
        {key:'categorie',label:'Categorie',type:'select',options:['Cereale & Oleaginoase','Ingrasaminte & Chimice','Combustibili & Lichide','Minerale & Agregate','Otel & Metale','Project Cargo','Containere','Altele'],def:'Altele'},
        {key:'search_patterns',label:'Patterns căutare (|)',hint:'grau|wheat|ble',type:'textarea'},
        {key:'stowage_factor',label:'Stowage Factor',hint:'1.0'},
        {key:'acn_tarif',label:'Tarif ACN (EUR/t)',hint:'0.50'},
        {key:'observatii',label:'Observații',type:'textarea'}
      ]}/>}
      <div className="card tbl-card"><div className="tbl-wrap"><table>
        <thead><tr>
          <th {...sM.thProps('cod')}>Cod{sM.arrow('cod')}</th>
          <th {...sM.thProps('nume_ro')}>Nume RO{sM.arrow('nume_ro')}</th>
          <th {...sM.thProps('nume_en')}>Nume EN{sM.arrow('nume_en')}</th>
          <th {...sM.thProps('categorie')}>Categorie{sM.arrow('categorie')}</th>
          <th>Patterns</th>
          <th {...sM.thProps('stowage_factor')}>SF{sM.arrow('stowage_factor')}</th>
          <th {...sM.thProps('acn_tarif')}>ACN{sM.arrow('acn_tarif')}</th>
          <th>Acțiuni</th>
        </tr></thead>
        <tbody>{sM.sorted.length===0&&<tr><td colSpan={8} className="empty">Nicio marfă găsită</td></tr>}
        {sM.sorted.map(m=><tr key={m.id}>
          <td><span className="mono" style={{color:'#f59e0b',fontWeight:700}}>{m.cod}</span></td>
          <td style={{fontWeight:500}}>{m.nume_ro||'—'}</td><td style={{fontSize:11}}>{m.nume_en||'—'}</td>
          <td><span className="badge" style={{background:'#1e293b',color:'#94a3b8',fontSize:10}}>{m.categorie||'—'}</span></td>
          <td style={{fontSize:10,maxWidth:200,overflow:'hidden',textOverflow:'ellipsis'}}>{m.search_patterns||'—'}</td>
          <td style={{fontSize:11,textAlign:'center'}}>{m.stowage_factor||'—'}</td>
          <td style={{fontSize:11,textAlign:'center'}}>{m.acn_tarif||'—'}</td>
          <td><button className="btn-sm" onClick={()=>setEM(m)} style={{marginRight:4}}>✏️</button>
            <button className="btn-sm" onClick={()=>delMarfa(m.id)} style={{color:'#ef4444'}}>🗑️</button></td>
        </tr>)}</tbody>
      </table></div></div>
    </div>}

    {tab==='navemaster'&&<NaveMasterTab/>}

    {tab==='quality'&&<div>
      {!dq ? <Loading/> : <div>
        <div className="card" style={{padding:20,marginBottom:16}}>
          <h3 style={{marginBottom:12,fontSize:14,color:'#e2e8f0'}}>Master Tables</h3>
          <div className="kpi-grid kpi-4">
            {Object.entries(dq.masters||{}).map(([k,v])=><Kpi key={k} label={k.replace('_',' ')} value={fmt(v)} hint="înregistrări" color="#0ea5e9"/>)}
          </div>
        </div>
        <div className="card tbl-card">
          <div className="tbl-head"><span className="tbl-title">Linking FK — Calitate date per tabel</span></div>
          <div className="tbl-wrap"><table>
            <thead><tr><th>Tabel</th><th>Total</th><th>Navă linked</th><th>Agent linked</th><th>Operator linked</th><th>Marfă linked</th></tr></thead>
            <tbody>{(dq.tables||[]).map(t=><tr key={t.table}>
              <td className="mono" style={{color:'#0ea5e9'}}>{t.table}</td>
              <td>{fmt(t.total)}</td>
              <td style={{color:t.nava_linked>0?'#10b981':'#64748b'}}>{t.nava_linked!=null?fmt(t.nava_linked)+' ('+Math.round((t.nava_linked/Math.max(t.total,1))*100)+'%)':'—'}</td>
              <td style={{color:t.agent_linked>0?'#10b981':'#64748b'}}>{t.agent_linked!=null?fmt(t.agent_linked)+' ('+Math.round((t.agent_linked/Math.max(t.total,1))*100)+'%)':'—'}</td>
              <td style={{color:t.oper_linked>0?'#10b981':'#64748b'}}>{t.oper_linked!=null?fmt(t.oper_linked)+' ('+Math.round((t.oper_linked/Math.max(t.total,1))*100)+'%)':'—'}</td>
              <td style={{color:t.marfa_linked>0?'#10b981':'#64748b'}}>{t.marfa_linked!=null?fmt(t.marfa_linked)+' ('+Math.round((t.marfa_linked/Math.max(t.total,1))*100)+'%)':'—'}</td>
            </tr>)}</tbody>
          </table></div>
        </div>
      </div>}
    </div>}

    {tab==='db'&&<div>
      {!db ? <Loading/> : <div className="grid-2">
        <div className="card" style={{padding:20}}>
          <h3 style={{marginBottom:12,fontSize:14,color:'#e2e8f0'}}>Tabele & volume</h3>
          {(db.tables||[]).map(t=><div key={t.tbl} className="setting-row">
            <span className="mono" style={{color:'#0ea5e9'}}>{t.tbl}</span>
            <span>{fmt(t.rows_est)} rânduri</span>
          </div>)}
        </div>
        <div className="card" style={{padding:20}}>
          <h3 style={{marginBottom:12,fontSize:14,color:'#e2e8f0'}}>Status</h3>
          <div className="setting-row"><span>Host</span><span className="mono">db01.tradingline.ro</span></div>
          <div className="setting-row"><span>Database</span><span className="mono">buletine_portuare</span></div>
          <div className="setting-row"><span>Status</span><span style={{color:'#10b981'}}>● Conectat</span></div>
          <div className="setting-row"><span>Version</span><span className="mono">v2.1 (Master Tables + FK Linking)</span></div>
        </div>
      </div>}
    </div>}
  </div>;
}

// ═══════════════════════════════════════════════
// MAIN APP
// ═══════════════════════════════════════════════
// ═══════════════════════════════════════════════
// ARMATORI PAGE — stacked bar armator × marfa
// ═══════════════════════════════════════════════
function ArmatoriPage({f}) {
  const [armatori,setArm]=useState([]);
  const [armMarfa,setAM]=useState([]);

  useEffect(()=>{
    api('/top-armatori?'+fQ(f)).then(d=>setArm(d||[]));
    api('/armator-marfa?'+fQ(f)).then(d=>setAM(d||[]));
  },[f.days,f.start,f.end,f.date,f.port]);

  // Build stacked data: armator as X, each marfa as a bar segment
  const marfaSet = new Set();
  const armMap = {};
  armMarfa.forEach(r => {
    marfaSet.add(r.marfa);
    if(!armMap[r.armator]) armMap[r.armator] = {armator:r.armator, total:0};
    armMap[r.armator][r.marfa] = Number(r.qty);
    armMap[r.armator].total += Number(r.qty);
  });
  const stackedData = Object.values(armMap).sort((a,b)=>b.total-a.total).slice(0,15);
  const marfaList = [...marfaSet].slice(0,8);

  return <div className="page-content">
    <div className="section-header">
      <h2>Armatori</h2>
      <p>Top armatori pe volum, detaliu pe marfă — {periodLabel(f)} · <span style={{color:'#64748b',fontSize:10}}>călătorii unice (deduplicate per escală)</span></p>
    </div>
    <div className="kpi-grid kpi-4">
      <Kpi label="Armatori activi" value={armatori.length} hint="din fl_af_sosire" color="#8b5cf6"/>
      <Kpi label="Volume totale" value={fmt(armatori.reduce((s,r)=>s+Number(r.qty||0),0))} hint="tone" color="#0ea5e9"/>
      <Kpi label="Top armator" value={armatori[0]?.armator||'—'} hint={fmt(armatori[0]?.qty)+' t'} color="#10b981"/>
      <Kpi label="Tipuri marfă" value={marfaList.length} hint="distincte" color="#f59e0b"/>
    </div>
    <ChartCard title="Armator × Marfă (tone) — stacked bar" h={400}>
      <ResponsiveContainer>
        <BarChart data={stackedData} layout="vertical">
          <CartesianGrid strokeDasharray="3 3" stroke="#1e293b"/>
          <XAxis type="number" tick={{fill:'#64748b',fontSize:11}}/>
          <YAxis dataKey="armator" type="category" width={140} tick={{fill:'#94a3b8',fontSize:9}}/>
          <Tooltip contentStyle={ttStyle} itemStyle={ttItem} labelStyle={ttLabel} formatter={v=>fmt(v)+' t'}/>
          <Legend/>
          {marfaList.map((m,i)=><Bar key={m} dataKey={m} stackId="a" fill={COLORS[i%COLORS.length]}/>)}
        </BarChart>
      </ResponsiveContainer>
    </ChartCard>
    <DataTable title="Top armatori" name="armatori" columns={[
      {key:'armator',label:'Armator'},{key:'unitati',label:'Unități'},{key:'qty',label:'Tone',render:v=>fmt(v)}
    ]} rows={armatori}/>
  </div>;
}

// ═══════════════════════════════════════════════
// CONVOAIE PAGE — grupare cap + barje
// ═══════════════════════════════════════════════
function ConvoaiePage({f}) {
  const [convoaie,setConv]=useState([]);
  const [expanded,setExp]=useState(null);
  const sortC = useSortable(convoaie);

  useEffect(()=>{ api('/convoaie').then(d=>setConv(d||[])); },[]);

  return <div className="page-content">
    <div className="section-header">
      <h2>Convoaie avizate (snapshot curent)</h2>
      <p>Grupare pe convoi cu detaliu barje — click pentru expandare</p>
    </div>
    <div className="kpi-grid kpi-4">
      <Kpi label="Convoaie" value={convoaie.length} hint="avizate sosire" color="#0ea5e9"/>
      <Kpi label="Barje total" value={convoaie.reduce((s,c)=>s+c.barje.length,0)} hint="unități" color="#10b981"/>
      <Kpi label="Tone total" value={fmt(convoaie.reduce((s,c)=>s+c.total_tone,0))} hint="avizate" color="#f59e0b"/>
      <Kpi label="Capacitate" value={fmt(convoaie.reduce((s,c)=>s+c.total_cap,0))} hint="tone max" color="#8b5cf6"/>
    </div>
    <div className="card tbl-card">
      <div className="tbl-head"><span className="tbl-title">Convoaie ({convoaie.length})</span></div>
      <div className="tbl-wrap">
        <table>
          <thead><tr>
            <th {...sortC.thProps('convoi')}>Convoi{sortC.arrow('convoi')}</th>
            <th {...sortC.thProps('armator')}>Armator{sortC.arrow('armator')}</th>
            <th {...sortC.thProps('agent')}>Agent{sortC.arrow('agent')}</th>
            <th {...sortC.thProps('hp')}>HP{sortC.arrow('hp')}</th>
            <th {...sortC.thProps('eta')}>ETA{sortC.arrow('eta')}</th>
            <th>Barje</th>
            <th {...sortC.thProps('total_tone')}>Tone{sortC.arrow('total_tone')}</th>
            <th {...sortC.thProps('total_cap')}>Capacitate{sortC.arrow('total_cap')}</th>
          </tr></thead>
          <tbody>
            {sortC.sorted.map((c,i)=><React.Fragment key={i}>
              <tr onClick={()=>setExp(expanded===i?null:i)} style={{cursor:'pointer',background:expanded===i?'rgba(14,165,233,0.08)':'transparent'}}>
                <td style={{fontWeight:600,color:'#e2e8f0'}}>{expanded===i?'▼':'▶'} {c.convoi}</td>
                <td>{c.armator||'—'}</td><td>{c.agent||'—'}</td><td>{c.hp||'—'}</td>
                <td style={c.eta&&new Date(c.eta)<new Date()?{color:'#ef4444',fontWeight:600}:{}}>{c.eta&&new Date(c.eta)<new Date()?'⏰ ':''}{fmtDate(c.eta)}</td><td>{c.barje.length}</td>
                <td style={{fontWeight:600}}>{fmt(c.total_tone)}</td><td>{fmt(c.total_cap)}</td>
              </tr>
              {expanded===i && c.barje.map((b,j)=><tr key={j} style={{background:'rgba(14,165,233,0.03)'}}>
                <td style={{paddingLeft:30,color:'#64748b'}}>↳ {b.nava||'—'}</td>
                <td style={{fontSize:11,color:'#64748b'}}>{b.armator||'—'}</td>
                <td>{b.agent||'—'}</td><td></td><td></td>
                <td><span className={'badge '+(b.tip_operatiune==='DESC'?'badge-amber':'badge-green')}>{b.tip_operatiune||'—'}</span></td>
                <td>{fmt(b.cantitate_tone)}</td><td>{fmt(b.capacitate_max)}</td>
              </tr>)}
            </React.Fragment>)}
          </tbody>
        </table>
      </div>
    </div>
  </div>;
}

// ═══════════════════════════════════════════════
// HEATMAP — operator × marfa
// ═══════════════════════════════════════════════
function HeatmapPage({f}) {
  const [data,setData]=useState([]);
  const [mProv,setMP]=useState([]);
  const [mDest,setMD]=useState([]);

  useEffect(()=>{
    api('/heatmap-operator-marfa?'+fQ(f)).then(d=>setData(d||[]));
    api('/marfa-prov?'+fQ(f)).then(d=>setMP(d||[]));
    api('/marfa-dest?'+fQ(f)).then(d=>setMD(d||[]));
  },[f.days,f.start,f.end,f.date,f.port]);

  // Build heatmap grid — sorted by total volume
  const heatMap = {};
  const opTotals = {}, marfaTotals = {};
  data.forEach(r => {
    heatMap[r.operator+'|'+r.marfa] = Number(r.qty);
    opTotals[r.operator] = (opTotals[r.operator]||0) + Number(r.qty);
    marfaTotals[r.marfa] = (marfaTotals[r.marfa]||0) + Number(r.qty);
  });
  const ops = Object.entries(opTotals).sort((a,b)=>b[1]-a[1]).slice(0,12).map(e=>e[0]);
  const marfe = Object.entries(marfaTotals).sort((a,b)=>b[1]-a[1]).slice(0,10).map(e=>e[0]);
  const maxVal = Math.max(...data.map(r=>Number(r.qty)), 1);

  // Marfa × Prov stacked
  const provSet = new Set();
  const mMap = {};
  mProv.forEach(r => {
    provSet.add(r.provenienta);
    if(!mMap[r.marfa]) mMap[r.marfa] = {marfa:r.marfa, total:0};
    mMap[r.marfa][r.provenienta] = Number(r.qty);
    mMap[r.marfa].total += Number(r.qty);
  });
  const mStackData = Object.values(mMap).sort((a,b)=>b.total-a.total).slice(0,12);
  const provList = [...provSet].slice(0,8);

  // Marfa × Destinație stacked
  const destSet = new Set();
  const dMap = {};
  mDest.forEach(r => {
    destSet.add(r.destinatie);
    if(!dMap[r.marfa]) dMap[r.marfa] = {marfa:r.marfa, total:0};
    dMap[r.marfa][r.destinatie] = Number(r.qty);
    dMap[r.marfa].total += Number(r.qty);
  });
  const dStackData = Object.values(dMap).sort((a,b)=>b.total-a.total).slice(0,12);
  const destList = [...destSet].slice(0,8);

  return <div className="page-content">
    <div className="section-header">
      <h2>Analiză Marfă × Operator × Proveniență</h2>
      <p>Heatmap și stacked bar — {periodLabel(f)}</p>
    </div>

    <div className="card" style={{padding:20}}>
      <div className="chart-title">Heatmap: Operator × Marfă (intensitate = tone)</div>
      {ops.length===0?<div className="empty" style={{padding:40}}>Nu sunt date operator×marfă pentru perioada selectată. Verifică dacă datele din buletine acoperă această perioadă.</div>:
      <div style={{overflowX:'auto'}}>
        <table style={{borderCollapse:'collapse',fontSize:11}}>
          <thead><tr><th style={{padding:'6px 10px',color:'#64748b'}}>Operator ↓ / Marfă →</th>
            {marfe.map(m=><th key={m} style={{padding:'6px 8px',color:'#94a3b8',maxWidth:80,whiteSpace:'nowrap',overflow:'hidden',textOverflow:'ellipsis'}} title={m}>{m}</th>)}
            <th style={{padding:'6px 8px',color:'#f59e0b',fontWeight:700}}>TOTAL</th>
          </tr></thead>
          <tbody>{ops.map(op=><tr key={op}>
            <td style={{padding:'6px 10px',color:'#e2e8f0',fontWeight:500,whiteSpace:'nowrap'}}>{op}</td>
            {marfe.map(m=>{
              const val = heatMap[op+'|'+m] || 0;
              const intensity = val / maxVal;
              const bg = val > 0 ? `rgba(14,165,233,${Math.max(0.1,intensity)})` : 'transparent';
              return <td key={m} style={{padding:'6px 8px',background:bg,color:val>0?'#e2e8f0':'#475569',textAlign:'center',fontWeight:val>0?500:400}}>
                {val > 0 ? fmt(val) : '-'}
              </td>;
            })}
            <td style={{padding:'6px 8px',textAlign:'center',fontWeight:700,color:'#f59e0b',background:'rgba(245,158,11,0.06)'}}>{fmt(opTotals[op]||0)}</td>
          </tr>)}
          <tr style={{borderTop:'2px solid #334155'}}>
            <td style={{padding:'6px 10px',fontWeight:700,color:'#f59e0b'}}>TOTAL</td>
            {marfe.map(m=><td key={m} style={{padding:'6px 8px',textAlign:'center',fontWeight:600,color:'#f59e0b',background:'rgba(245,158,11,0.06)'}}>{fmt(marfaTotals[m]||0)}</td>)}
            <td style={{padding:'6px 8px',textAlign:'center',fontWeight:700,color:'#10b981',background:'rgba(16,185,129,0.08)'}}>{fmt(Object.values(opTotals).reduce((s,v)=>s+v,0))}</td>
          </tr>
          </tbody>
        </table>
      </div>}
    </div>

    <ChartCard title="Marfă × Proveniență (tone) — stacked bar" h={400}>
      {mStackData.length===0?<div className="empty">Nu sunt date proveniență pentru perioada selectată</div>:
      <ResponsiveContainer>
        <BarChart data={mStackData}>
          <CartesianGrid strokeDasharray="3 3" stroke="#1e293b"/>
          <XAxis dataKey="marfa" tick={{fill:'#64748b',fontSize:9}} angle={-20} textAnchor="end" height={60}/>
          <YAxis tick={{fill:'#64748b',fontSize:11}}/>
          <Tooltip contentStyle={ttStyle} itemStyle={ttItem} labelStyle={ttLabel} formatter={v=>fmt(v)+' t'}/>
          <Legend/>
          {provList.map((p,i)=><Bar key={p} dataKey={p} stackId="a" fill={COLORS[i%COLORS.length]}/>)}
        </BarChart>
      </ResponsiveContainer>}
    </ChartCard>

    <ChartCard title="Marfă × Către Porturi (tone) — stacked bar" h={400}>
      {dStackData.length===0?<div className="empty">Nu sunt date destinații pentru perioada selectată</div>:
      <ResponsiveContainer>
        <BarChart data={dStackData}>
          <CartesianGrid strokeDasharray="3 3" stroke="#1e293b"/>
          <XAxis dataKey="marfa" tick={{fill:'#64748b',fontSize:9}} angle={-20} textAnchor="end" height={60}/>
          <YAxis tick={{fill:'#64748b',fontSize:11}}/>
          <Tooltip contentStyle={ttStyle} itemStyle={ttItem} labelStyle={ttLabel} formatter={v=>fmt(v)+' t'}/>
          <Legend/>
          {destList.map((d,i)=><Bar key={d} dataKey={d} stackId="a" fill={COLORS[(i+3)%COLORS.length]}/>)}
        </BarChart>
      </ResponsiveContainer>}
    </ChartCard>
  </div>;
}

// ═══════════════════════════════════════════════
// PORT AGENCY — nave avizate + VesselFinder links
// ═══════════════════════════════════════════════
function AgencyPage({f}) {
  const [arrivals,setArr]=useState([]);
  const [stats,setStats]=useState({byAgent:[],noAgent:[]});
  const [fluvial,setFluv]=useState([]);
  const [flStats,setFlStats]=useState({byArmator:[],byAgent:[],noAgent:[]});
  const [tab,setTab]=useState('mt_arrivals');

  useEffect(()=>{
    api('/agency-arrivals?'+fQ(f)).then(d=>setArr(d||[]));
    api('/agency-stats?'+fQ(f)).then(d=>setStats(d||{byAgent:[],noAgent:[]}));
    api('/agency-fluvial?'+fQ(f)).then(d=>setFluv(d||[]));
    api('/agency-fluvial-stats?'+fQ(f)).then(d=>setFlStats(d||{byArmator:[],byAgent:[],noAgent:[]}));
  },[f.days,f.start,f.end,f.date,f.port]);

  const vfLink = (name) => {
    if(!name) return '#';
    return 'https://www.vesselfinder.com/vessels?name='+encodeURIComponent(name.replace(/[^a-zA-Z0-9 ]/g,'').trim());
  };

  const avizate = arrivals.filter(r=>r.status==='Avizată');
  const inRada = arrivals.filter(r=>r.status==='În radă');
  const faraAgentMt = stats.noAgent||[];
  const faraAgentFl = flStats.noAgent||[];

  return <div className="page-content">
    <div className="section-header">
      <h2>Port Agency — Trading Line</h2>
      <p>Nave maritime + convoaie fluviale · Oportunități agenturare · VesselFinder</p>
    </div>
    <div className="kpi-grid">
      <Kpi label="Maritime avizate" value={avizate.length} hint="nave" color="#0ea5e9"/>
      <Kpi label="Maritime în radă" value={inRada.length} hint="nave" color="#f59e0b"/>
      <Kpi label="Fluvial convoaie" value={fluvial.length} hint="cap convoi" color="#10b981"/>
      <Kpi label="Fără agent MT" value={faraAgentMt.length} hint="oportunitate!" color="#ef4444"/>
      <Kpi label="Fără agent FL" value={faraAgentFl.length} hint="oportunitate!" color="#ec4899"/>
    </div>

    <div style={{display:'flex',gap:6,marginBottom:16,flexWrap:'wrap'}}>
      <span style={{color:'#64748b',fontSize:10,lineHeight:'28px',marginRight:4}}>MARITIM:</span>
      {[['mt_arrivals','Nave Avizate'],['mt_rada','În Radă'],['mt_noagent','Fără Agent ⚠️']].map(([id,label])=>
        <button key={id} onClick={()=>setTab(id)} className={tab===id?'btn-primary':'btn-sm'}>{label}</button>
      )}
      <span style={{color:'#64748b',fontSize:10,lineHeight:'28px',margin:'0 8px'}}>|</span>
      <span style={{color:'#64748b',fontSize:10,lineHeight:'28px',marginRight:4}}>FLUVIAL:</span>
      {[['fl_convoaie','Convoaie Sosire'],['fl_armatori','Top Armatori'],['fl_noagent','Fără Agent ⚠️']].map(([id,label])=>
        <button key={id} onClick={()=>setTab(id)} className={tab===id?'btn-primary':'btn-sm'}>{label}</button>
      )}
      <span style={{color:'#64748b',fontSize:10,lineHeight:'28px',margin:'0 8px'}}>|</span>
      <button onClick={()=>setTab('map')} className={tab==='map'?'btn-primary':'btn-sm'}>Hartă Port</button>
    </div>

    {tab==='mt_arrivals'&&<DataTable title={'Nave maritime avizate ('+avizate.length+')'} name="agency_mt_avizate" columns={[
      {key:'nava',label:'Navă',render:(v)=>v?<a href={vfLink(v)} target="_blank" rel="noopener" style={{color:'#38bdf8',textDecoration:'none',fontWeight:600}}>🚢 {v}</a>:'—'},
      {key:'agent',label:'Agent',render:v=>v?<span className={'badge '+(v.includes('TDL')?'badge-green':'badge-blue')}>{v}</span>:<span className="badge badge-red">FĂRĂ</span>},
      {key:'pavilion',label:'Pav'},{key:'loa',label:'LOA'},{key:'data_estimata',label:'ETA',render:fmtDate},
      {key:'marfa',label:'Marfă'},{key:'cantitate_tone',label:'Tone',render:v=>fmt(v)},
      {key:'provenienta',label:'Prov.'},{key:'operator',label:'Operator'},
    ]} rows={avizate}/>}

    {tab==='mt_rada'&&<DataTable title={'Maritime în radă ('+inRada.length+')'} name="agency_mt_rada" columns={[
      {key:'nava',label:'Navă',render:(v)=>v?<a href={vfLink(v)} target="_blank" rel="noopener" style={{color:'#38bdf8',textDecoration:'none',fontWeight:600}}>🚢 {v}</a>:'—'},
      {key:'agent',label:'Agent',render:v=>v||<span className="badge badge-red">FĂRĂ</span>},
      {key:'data_estimata',label:'Sosire',render:fmtDate},{key:'scop',label:'Scop'},
      {key:'marfa',label:'Marfă'},{key:'cantitate_tone',label:'Tone',render:v=>fmt(v)},{key:'operator',label:'Operator'},
    ]} rows={inRada}/>}

    {tab==='mt_noagent'&&<div>
      <div className="card" style={{padding:16,marginBottom:16,borderLeft:'3px solid #ef4444'}}>
        <div style={{fontSize:13,fontWeight:600,color:'#e2e8f0'}}>Oportunități agenturare maritimă</div>
        <div style={{fontSize:12,color:'#94a3b8'}}>Nave fără agent declarat — contact direct armator pentru ofertă TDL Port Agency.</div>
      </div>
      <DataTable title={'Maritime fără agent ('+faraAgentMt.length+')'} name="agency_mt_fara" columns={[
        {key:'nava',label:'Navă',render:(v)=>v?<a href={vfLink(v)} target="_blank" rel="noopener" style={{color:'#ef4444',fontWeight:700}}>⚠️ {v}</a>:'—'},
        {key:'pavilion',label:'Pav'},{key:'loa',label:'LOA'},{key:'eta',label:'ETA',render:fmtDate},
        {key:'marfa',label:'Marfă'},{key:'cantitate_tone',label:'Tone',render:v=>fmt(v)},
        {key:'provenienta',label:'Prov.'},{key:'operator',label:'Operator'},
      ]} rows={faraAgentMt}/>
    </div>}

    {tab==='fl_convoaie'&&<DataTable title={'Convoaie fluviale avizate sosire ('+fluvial.length+')'} name="agency_fl_convoaie" columns={[
      {key:'convoi',label:'Convoi',render:v=><span style={{fontWeight:600,color:'#e2e8f0'}}>⛵ {v}</span>},
      {key:'nava',label:'Cap Convoi'},{key:'armator',label:'Armator',render:v=>v?<span style={{color:'#f59e0b',fontWeight:500}}>{v}</span>:'—'},
      {key:'agent',label:'Agent',render:v=>v?<span className={'badge '+(v.includes('TDL')?'badge-green':'badge-blue')}>{v}</span>:<span className="badge badge-red">FĂRĂ</span>},
      {key:'hp',label:'HP'},{key:'eta',label:'ETA',render:fmtDate},
      {key:'nr_barje',label:'Barje'},{key:'total_tone',label:'Tone',render:v=>fmt(v)},
      {key:'marfuri',label:'Mărfuri'},{key:'origini',label:'Origini'},{key:'destinatii',label:'Dest.'},
    ]} rows={fluvial}/>}

    {tab==='fl_armatori'&&<div>
      <ChartCard title="Top armatori fluviali (nr convoaie)" h={350}>
        <ResponsiveContainer>
          <BarChart data={(flStats.byArmator||[]).slice(0,12)} layout="vertical">
            <CartesianGrid strokeDasharray="3 3" stroke="#1e293b"/>
            <XAxis type="number" tick={{fill:'#64748b',fontSize:11}}/>
            <YAxis dataKey="armator" type="category" width={140} tick={{fill:'#94a3b8',fontSize:9}}/>
            <Tooltip contentStyle={ttStyle} itemStyle={ttItem} labelStyle={ttLabel}/>
            <Bar dataKey="convoaie" fill="#10b981" radius={[0,4,4,0]}/>
          </BarChart>
        </ResponsiveContainer>
      </ChartCard>
      <DataTable title="Armatori fluviali" name="agency_fl_armatori" columns={[
        {key:'armator',label:'Armator'},{key:'convoaie',label:'Convoaie'},{key:'total_hp',label:'HP Total',render:v=>fmt(v)}
      ]} rows={flStats.byArmator||[]}/>
    </div>}

    {tab==='fl_noagent'&&<div>
      <div className="card" style={{padding:16,marginBottom:16,borderLeft:'3px solid #ec4899'}}>
        <div style={{fontSize:13,fontWeight:600,color:'#e2e8f0'}}>Oportunități agenturare fluvială</div>
        <div style={{fontSize:12,color:'#94a3b8'}}>Convoaie fără agent — armator identificat pe capul de convoi. Contact direct pentru ofertă agenturare Dunăre.</div>
      </div>
      <DataTable title={'Convoaie fluviale fără agent ('+faraAgentFl.length+')'} name="agency_fl_fara" columns={[
        {key:'convoi',label:'Convoi',render:v=><span style={{color:'#ec4899',fontWeight:700}}>⚠️ {v}</span>},
        {key:'nava',label:'Cap Convoi'},{key:'armator',label:'Armator',render:v=><span style={{color:'#f59e0b',fontWeight:600}}>{v||'—'}</span>},
        {key:'hp',label:'HP'},{key:'eta',label:'ETA',render:fmtDate},{key:'pavilion',label:'Pav'},
      ]} rows={faraAgentFl}/>
    </div>}

    {tab==='map'&&<div className="card" style={{overflow:'hidden',borderRadius:10}}>
      <div style={{padding:'12px 16px',borderBottom:'1px solid #1e293b',display:'flex',justifyContent:'space-between',alignItems:'center'}}>
        <span style={{fontSize:13,fontWeight:600,color:'#e2e8f0'}}>Port Constanța — VesselFinder</span>
        <a href="https://www.vesselfinder.com/pro/map#port-details?id=ROCND001" target="_blank" rel="noopener" className="btn-sm">Deschide complet ↗</a>
      </div>
      <iframe src="https://www.vesselfinder.com/ports/ROCND001" style={{width:'100%',height:600,border:'none',background:'#0a0e17'}} title="VesselFinder"/>
    </div>}
  </div>;
}

// ═══════════════════════════════════════════════
// NAVE FLUVIALE ÎN PORT — taxare portuară
// ═══════════════════════════════════════════════
function NaveFluPage({f}) {
  const [data,setData]=useState(null);
  const [tab,setTab]=useState('auto');
  const [expandedArm,setExpArm]=useState(null);

  useEffect(()=>{ api('/nfip-port-dues').then(d=>setData(d)); },[]);

  if(!data) return <Loading/>;

  const getBracket = (zile) => {
    if(!zile && zile!==0) return '—';
    if(zile<=10) return '1-10 zile';
    if(zile<=20) return '11-20 zile';
    if(zile<=30) return '21-30 zile';
    if(zile<=60) return '31-60 zile';
    return '60+ zile';
  };
  const getBracketColor = (zile) => {
    if(!zile && zile!==0) return '#64748b';
    if(zile<=10) return '#10b981';
    if(zile<=20) return '#0ea5e9';
    if(zile<=30) return '#f59e0b';
    if(zile<=60) return '#ef4444';
    return '#dc2626';
  };
  const getTarif = (zile, tip) => {
    const t = data.tarife[tip];
    if(!zile && zile!==0) return 0;
    if(zile<=10) return t[0].tarif;
    if(zile<=20) return t[1].tarif;
    if(zile<=30) return t[2].tarif;
    if(zile<=60) return t[3].tarif;
    return t[4].tarif;
  };

  const currentList = tab==='auto' ? data.autopropulsate : data.nepropulsate;
  const tipLabel = tab==='auto' ? 'Autopropulsate' : 'Nepropulsate';
  const totalNave = currentList.reduce((s,a)=>s+a.nave.length,0);

  return <div className="page-content">
    <div className="section-header">
      <h2>Nave Fluviale în Port — Taxare Portuară</h2>
      <p>Snapshot {fmtDate(data.snapshot)} · {data.total_nave} nave total · Tarif infraportuară APC 2026</p>
    </div>

    <div className="kpi-grid kpi-4">
      <Kpi label="Total nave în port" value={data.total_nave} hint="fluviale" color="#0ea5e9"/>
      <Kpi label="Autopropulsate" value={data.autopropulsate.reduce((s,a)=>s+a.nave.length,0)} hint="tarif 4.27-8.54 €/100TC-zi" color="#10b981"/>
      <Kpi label="Nepropulsate" value={data.nepropulsate.reduce((s,a)=>s+a.nave.length,0)} hint="tarif 1.07-2.13 €/100TC-zi" color="#f59e0b"/>
      <Kpi label="Armatori distincti" value={data.autopropulsate.length + data.nepropulsate.length} hint="în port azi" color="#8b5cf6"/>
    </div>

    <div style={{display:'flex',gap:8,marginBottom:16}}>
      <button onClick={()=>{setTab('auto');setExpArm(null)}} className={tab==='auto'?'btn-primary':'btn-sm'}>
        Autopropulsate ({data.autopropulsate.reduce((s,a)=>s+a.nave.length,0)})
      </button>
      <button onClick={()=>{setTab('nepro');setExpArm(null)}} className={tab==='nepro'?'btn-primary':'btn-sm'}>
        Nepropulsate ({data.nepropulsate.reduce((s,a)=>s+a.nave.length,0)})
      </button>
    </div>

    {/* Tariff reference */}
    <div className="card" style={{padding:12,marginBottom:16,display:'flex',gap:16,flexWrap:'wrap',fontSize:11,color:'#94a3b8'}}>
      <span style={{fontWeight:600,color:'#e2e8f0'}}>Tarife {tipLabel} (EUR/100TC-zi):</span>
      {(data.tarife[tab==='auto'?'autopropulsate':'nepropulsate']).map(t=>
        <span key={t.zile}><span style={{color:getBracketColor(t.zile==='60+'?61:parseInt(t.zile)),fontWeight:600}}>{t.zile}:</span> {t.tarif}</span>
      )}
    </div>

    {/* Armator groups */}
    <div className="card tbl-card">
      <div className="tbl-head"><span className="tbl-title">{tipLabel} — per Armator ({currentList.length} armatori, {totalNave} nave)</span></div>
      <div className="tbl-wrap"><table>
        <thead><tr><th>Armator</th><th>Nave</th><th>Max zile</th><th>Bracket maxim</th><th>Tone total</th></tr></thead>
        <tbody>
          {currentList.map((arm,i)=><React.Fragment key={i}>
            <tr onClick={()=>setExpArm(expandedArm===i?null:i)} style={{cursor:'pointer',background:expandedArm===i?'rgba(14,165,233,0.08)':'transparent'}}>
              <td style={{fontWeight:600,color:'#e2e8f0'}}>{expandedArm===i?'▼':'▶'} {arm.armator}</td>
              <td>{arm.nave.length}</td>
              <td><span style={{color:arm.max_zile>365?'#64748b':getBracketColor(arm.max_zile),fontWeight:600}}>{arm.max_zile>365?'⚠️ dată invalidă':(arm.max_zile || '—')+' zile'}</span></td>
              <td><span className="badge" style={{background:arm.max_zile>365?'#64748b22':getBracketColor(arm.max_zile)+'22',color:arm.max_zile>365?'#64748b':getBracketColor(arm.max_zile)}}>{arm.max_zile>365?'invalid':getBracket(arm.max_zile)}</span></td>
              <td>{fmt(arm.total_tone)}</td>
            </tr>
            {expandedArm===i && arm.nave.map((n,j)=><tr key={j} style={{background:'rgba(14,165,233,0.03)',fontSize:12}}>
              <td style={{paddingLeft:30,color:'#94a3b8'}}>↳ {n.nava||n.escala||'—'}</td>
              <td><span style={{color:'#64748b'}}>{n.dana||'—'}</span></td>
              <td><span style={{color:n.zile_port>365?'#64748b':getBracketColor(n.zile_port),fontWeight:600}}>{n.zile_port!==null?(n.zile_port>365?'⚠️':n.zile_port+'z'):'—'}</span></td>
              <td>
                <span className="badge" style={{background:getBracketColor(n.zile_port)+'22',color:getBracketColor(n.zile_port),fontSize:10}}>
                  {getBracket(n.zile_port)} · {getTarif(n.zile_port,tab==='auto'?'autopropulsate':'nepropulsate')} €
                </span>
              </td>
              <td style={{fontSize:11}}>
                {n.marfa ? <span>{n.marfa} · {fmt(n.cantitate)}t</span> : <span style={{color:'#475569'}}>fără marfă</span>}
                {n.provenienta ? <span style={{color:'#64748b'}}> · {n.provenienta}→{n.destinatie||'?'}</span> : ''}
              </td>
            </tr>)}
          </React.Fragment>)}
        </tbody>
      </table></div>
    </div>
  </div>;
}

// ═══════════════════════════════════════════════
// FLEET INTELLIGENCE — active/inactive pie + categories + drill-down
// ═══════════════════════════════════════════════
function FleetIntelPage({f}) {
  const [data,setData]=useState(null);
  const [stats,setStats]=useState(null);
  const [nav,setNav]=useState('Fluvial');
  const [days,setDays]=useState(30);
  const [status,setStatus]=useState('');
  const [tipNava,setTipNava]=useState('');
  const sortV = useSortable(data?.vessels);

  const load = () => {
    const p = `nav=${nav}&days=${days}${status?'&status='+status:''}${tipNava?'&tipNava='+tipNava:''}`;
    api('/fleet-intel?'+p).then(setData);
    api('/nave-master/stats').then(setStats);
  };
  useEffect(load,[nav,days,status,tipNava]);

  if(!data||!stats) return <Loading/>;

  const pieColors = {'Activ':'#10b981','Inactiv':'#f59e0b','Neactiv':'#ef4444'};
  const totalPie = data.pie.reduce((s,r)=>s+Number(r.cnt),0);

  return <div className="page-content">
    <div className="section-header">
      <h2>Fleet Intelligence</h2>
      <p>Monitorizare flotă — {totalPie} nave văzute în buletine · Threshold: {days} zile</p>
    </div>

    {/* Filters */}
    <div style={{display:'flex',gap:8,marginBottom:16,flexWrap:'wrap',alignItems:'center'}}>
      <select value={nav} onChange={e=>{setNav(e.target.value);setTipNava('');}} className="input-sm">
        <option value="">Toate</option>
        <option value="Fluvial">Fluvial</option>
        <option value="Maritim">Maritim</option>
      </select>
      <select value={days} onChange={e=>setDays(Number(e.target.value))} className="input-sm">
        <option value="7">7 zile</option><option value="14">14 zile</option>
        <option value="30">30 zile</option><option value="60">60 zile</option>
        <option value="90">90 zile</option><option value="180">180 zile</option>
      </select>
      {data.tipNave?.length>0 && <select value={tipNava} onChange={e=>setTipNava(e.target.value)} className="input-sm">
        <option value="">Toate tipurile</option>
        {data.tipNave.map(t=><option key={t} value={t}>{t}</option>)}
      </select>}
      <select value={status} onChange={e=>setStatus(e.target.value)} className="input-sm">
        <option value="">Toate statusurile</option>
        <option value="activ">✅ Active (≤{days}z)</option>
        <option value="inactiv">⚠️ Inactive ({days}-{days*3}z)</option>
        <option value="neactiv">⚪ Neactive (>{days*3}z)</option>
      </select>
      <span style={{color:'#64748b',fontSize:11}}>{data.vessels?.length||0} nave afișate</span>
    </div>

    <div className="kpi-grid kpi-4">
      {data.pie.map(r=><Kpi key={r.status} label={r.status} value={r.cnt} 
        hint={totalPie?Math.round(r.cnt/totalPie*100)+'%':''} 
        color={pieColors[r.status]||'#64748b'}/>)}
      <Kpi label="Total master" value={stats.total} hint={`${stats.synced||0} API synced`} color="#0ea5e9"/>
    </div>

    <div className="grid-2">
      {/* Pie Chart */}
      <ChartCard title={`Active vs Inactive (${nav||'Toate'}, ${days}z threshold)`} h={300}>
        <ResponsiveContainer>
          <PieChart>
            <Pie data={data.pie} dataKey="cnt" nameKey="status" cx="50%" cy="50%" innerRadius={50} outerRadius={100}
              label={({name,percent})=>`${name} ${(percent*100).toFixed(0)}%`} labelLine={false}
              style={{fontSize:11}}>
              {data.pie.map((r,i)=><Cell key={i} fill={pieColors[r.status]||COLORS[i]} stroke="none"/>)}
            </Pie>
            <Tooltip contentStyle={ttStyle} itemStyle={ttItem} labelStyle={ttLabel}/>
            <Legend/>
          </PieChart>
        </ResponsiveContainer>
      </ChartCard>

      {/* Categories Bar */}
      <ChartCard title="Per tip navă (activ vs inactiv)" h={300}>
        <ResponsiveContainer>
          <BarChart data={data.categories} layout="vertical">
            <CartesianGrid strokeDasharray="3 3" stroke="#1e293b"/>
            <XAxis type="number" tick={{fill:'#64748b',fontSize:11}}/>
            <YAxis dataKey="tip_nava" type="category" tick={{fill:'#94a3b8',fontSize:9}} width={80}/>
            <Tooltip contentStyle={ttStyle} itemStyle={ttItem} labelStyle={ttLabel}/>
            <Legend/>
            <Bar dataKey="activ" stackId="a" fill="#10b981" name="Active"/>
            <Bar dataKey="inactiv" stackId="a" fill="#f59e0b" name="Inactive"/>
          </BarChart>
        </ResponsiveContainer>
      </ChartCard>
    </div>

    {/* Vessel List */}
    <div className="card tbl-card">
      <div className="tbl-head"><span className="tbl-title">
        Nave {status||'toate'} — {data.vessels?.length||0} rezultate
        {!status && <span style={{fontSize:11,color:'#64748b'}}> (selectează status din filtre)</span>}
      </span></div>
      <div className="tbl-wrap"><table>
        <thead><tr>
          <th {...sortV.thProps('id_apmc')}>ID{sortV.arrow('id_apmc')}</th>
          <th {...sortV.thProps('denumire_nava')}>Navă{sortV.arrow('denumire_nava')}</th>
          <th {...sortV.thProps('tip_nava')}>Tip{sortV.arrow('tip_nava')}</th>
          <th {...sortV.thProps('tip_navigatie')}>Nav{sortV.arrow('tip_navigatie')}</th>
          <th {...sortV.thProps('pavilion')}>Pavilion{sortV.arrow('pavilion')}</th>
          <th {...sortV.thProps('owner_text')}>Owner{sortV.arrow('owner_text')}</th>
          <th {...sortV.thProps('putere_hp')}>HP{sortV.arrow('putere_hp')}</th>
          <th {...sortV.thProps('calc_status')}>Status{sortV.arrow('calc_status')}</th>
          <th {...sortV.thProps('last_seen_buletin')}>Last seen{sortV.arrow('last_seen_buletin')}</th>
          <th {...sortV.thProps('zile_inactiv')}>Zile{sortV.arrow('zile_inactiv')}</th>
        </tr></thead>
        <tbody>{sortV.sorted.map((r,i)=><tr key={i} style={{opacity:r.calc_status==='neactiv'?0.5:1}}>
          <td><a href={`https://www.portofconstantza.com/pn/ro/nava/${r.id_apmc}`} target="_blank" style={{color:'#0ea5e9',fontSize:11}}>{r.id_apmc}</a></td>
          <td style={{fontWeight:600,color:'#e2e8f0'}}>{r.denumire_nava}</td>
          <td style={{fontSize:11}}>{r.tip_nava||'—'}</td>
          <td style={{fontSize:11}}>{r.tip_navigatie||'—'}</td>
          <td>{r.pavilion||'—'}</td>
          <td style={{fontSize:11,maxWidth:180,overflow:'hidden',textOverflow:'ellipsis'}}>{r.owner_text||'—'}</td>
          <td>{r.putere_hp||'—'}</td>
          <td><span className="badge" style={{background:r.calc_status==='activ'?'#10b98122':r.calc_status==='inactiv'?'#f59e0b22':'#ef444422',
            color:r.calc_status==='activ'?'#10b981':r.calc_status==='inactiv'?'#f59e0b':'#ef4444',fontSize:10}}>
            {r.calc_status}</span></td>
          <td style={{fontSize:11}}>{fmtDate(r.last_seen_buletin)||'—'}</td>
          <td><span style={{color:r.zile_inactiv<=days?'#10b981':r.zile_inactiv<=days*3?'#f59e0b':'#ef4444',fontWeight:600}}>{r.zile_inactiv}z</span></td>
        </tr>)}</tbody>
      </table></div>
    </div>
  </div>;
}

// ═══════════════════════════════════════════════
// NAVE MASTER — Settings Tab
// ═══════════════════════════════════════════════
function NaveMasterTab() {
  const [data,setData]=useState(null);
  const [search,setSearch]=useState('');
  const [tipFilter,setTipFilter]=useState('');
  const [statusFilter,setStatusFilter]=useState('');
  const [editing,setEditing]=useState(null);
  
  const load = () => {
    const params = new URLSearchParams();
    if(search) params.set('search',search);
    if(tipFilter) params.set('tip',tipFilter);
    if(statusFilter) params.set('status',statusFilter);
    params.set('limit','50');
    api('/nave-master?'+params).then(setData);
  };
  useEffect(load,[]);
  
  const saveEdit = async (id_apmc, fields) => {
    await api(`/nave-master/${id_apmc}`,{method:'PUT',headers:{'Content-Type':'application/json'},body:JSON.stringify(fields)});
    setEditing(null);
    load();
  };

  if(!data) return <Loading/>;
  return <div>
    <div style={{display:'flex',gap:8,marginBottom:12,flexWrap:'wrap'}}>
      <input value={search} onChange={e=>setSearch(e.target.value)} onKeyDown={e=>e.key==='Enter'&&load()}
        placeholder="Caută navă, owner, IMO..." className="input-sm" style={{width:250}}/>
      <select value={tipFilter} onChange={e=>{setTipFilter(e.target.value);setTimeout(load,50)}} className="input-sm">
        <option value="">Toate tipurile</option>
        <option value="Fluvial">Fluvial</option>
        <option value="Maritim">Maritim</option>
      </select>
      <select value={statusFilter} onChange={e=>{setStatusFilter(e.target.value);setTimeout(load,50)}} className="input-sm">
        <option value="">Toate statusurile</option>
        <option value="activ">Activ</option>
        <option value="inactiv">Inactiv</option>
        <option value="scrap">Scrap</option>
        <option value="necunoscut">Necunoscut</option>
      </select>
      <button onClick={load} className="btn-primary">Caută</button>
      <span style={{color:'#64748b',fontSize:11,alignSelf:'center'}}>{data.total} rezultate</span>
    </div>
    <div className="tbl-wrap"><table>
      <thead><tr><th>ID APMC</th><th>Navă</th><th>Tip</th><th>Nav</th><th>Pavilion</th><th>Owner</th><th>LOA</th><th>HP</th><th>Status</th><th>Last seen</th><th>Edit</th></tr></thead>
      <tbody>{data.rows.map((r,i)=><tr key={i}>
        <td><a href={`https://www.portofconstantza.com/pn/ro/nava/${r.id_apmc}`} target="_blank" style={{color:'#0ea5e9'}}>{r.id_apmc}</a></td>
        <td style={{fontWeight:600}}>{r.denumire_nava}</td>
        <td>{r.tip_nava||'—'}</td>
        <td>{r.tip_navigatie||'—'}</td>
        <td>{r.pavilion||'—'}</td>
        <td style={{fontSize:11,maxWidth:150,overflow:'hidden',textOverflow:'ellipsis'}}>{r.owner_text||r.owner_tdl_system||'—'}</td>
        <td>{r.loa||'—'}</td>
        <td>{r.putere_hp||'—'}</td>
        <td>
          {editing===r.id_apmc?
            <select defaultValue={r.status_flota||'necunoscut'} onChange={e=>saveEdit(r.id_apmc,{status_flota:e.target.value,tip_nava:r.tip_nava,tip_navigatie:r.tip_navigatie,observatii:r.observatii})} className="input-sm">
              <option value="activ">Activ</option><option value="inactiv">Inactiv</option>
              <option value="scrap">Scrap</option><option value="necunoscut">Necunoscut</option>
            </select>
          : <span className="badge" style={{background:r.status_flota==='activ'?'#10b98122':r.status_flota==='inactiv'?'#f59e0b22':'#64748b22',
              color:r.status_flota==='activ'?'#10b981':r.status_flota==='inactiv'?'#f59e0b':'#64748b'}}>
              {r.status_flota||'?'} {r.zile_inactiv!=null?`(${r.zile_inactiv}z)`:''}
            </span>}
        </td>
        <td style={{fontSize:11}}>{fmtDate(r.last_seen_buletin)||'—'}</td>
        <td><button onClick={()=>setEditing(editing===r.id_apmc?null:r.id_apmc)} className="btn-sm" style={{fontSize:10}}>✏️</button></td>
      </tr>)}</tbody>
    </table></div>
  </div>;
}

// ═══════════════════════════════════════════════
// FLOTĂ FLUVIALĂ — Capacitate & Leverage
// ═══════════════════════════════════════════════
function FlotaPage({f}) {
  const [data,setData]=useState(null);
  const [days,setDays]=useState(7);
  const [expandCat,setExpandCat]=useState(null);

  useEffect(()=>{ api('/flota-capacity?days='+days).then(setData); },[days]);
  if(!data) return <Loading/>;

  const capIn = data.inPortTotal?.cap || 0;
  const capArr = data.arriving?.cap || 0;
  const capDep = data.departing?.cap || 0;
  const capColors = {Autopropulsate:'#0ea5e9',Barje:'#10b981',Tankuri:'#f59e0b'};

  // Leverage pie data
  const leveragePie = [
    {name:'În port Constanța', value: capIn},
    {name:'Vine spre CTA (avizat)', value: capArr},
    {name:'Pleacă din CTA', value: capDep},
  ];
  const levColors = ['#10b981','#0ea5e9','#ef4444'];

  return <div className="page-content">
    <div className="section-header">
      <h2>Flotă Fluvială — Capacitate & Leverage</h2>
      <p>Snapshot {fmtDate(data.snapshot)} · Ce capacitate am disponibilă pentru cotație?</p>
    </div>

    <div style={{display:'flex',gap:8,marginBottom:16,alignItems:'center'}}>
      <span style={{color:'#94a3b8',fontSize:12}}>Flotă activă din ultimele:</span>
      {[7,14,30,60,90,180].map(d=><button key={d} onClick={()=>setDays(d)} 
        className={days===d?'btn-primary':'btn-sm'}>{d} zile</button>)}
    </div>

    <div className="kpi-grid kpi-4">
      <Kpi label="În port acum" value={data.inPortTotal?.cnt||0} hint={fmt(capIn)+' t capacitate'} color="#10b981"/>
      <Kpi label="Vine spre CTA" value={data.arriving?.convoys||0} hint={fmt(capArr)+' t pe '+data.arriving?.barges+' barje'} color="#0ea5e9"/>
      <Kpi label="Pleacă din CTA" value={data.departing?.convoys||0} hint={fmt(capDep)+' t pe '+data.departing?.barges+' barje'} color="#ef4444"/>
      <Kpi label="Flotă totală activă" value={data.totalFleet?.reduce((s,r)=>s+Number(r.cnt),0)||0} 
        hint={fmt(data.totalFleet?.reduce((s,r)=>s+Number(r.cap_total),0)||0)+' t total'} color="#8b5cf6"/>
    </div>

    <div className="grid-2">
      {/* Pie: Capacitate în port per categorie */}
      <ChartCard title="Capacitate în port per categorie" h={300}>
        <ResponsiveContainer>
          <PieChart>
            <Pie data={data.inPort.filter(r=>r.cap>0)} dataKey="cap" nameKey="categorie" cx="50%" cy="50%" innerRadius={45} outerRadius={95}
              label={({categorie,cap})=>categorie+': '+fmt(cap)+'t'} style={{fontSize:10}}>
              {data.inPort.map((r,i)=><Cell key={i} fill={capColors[r.categorie]||COLORS[i]}/>)}
            </Pie>
            <Tooltip contentStyle={ttStyle} itemStyle={ttItem} labelStyle={ttLabel} formatter={v=>fmt(v)+' t'}/>
          </PieChart>
        </ResponsiveContainer>
      </ChartCard>

      {/* Pie: Leverage — unde e capacitatea */}
      <ChartCard title="Leverage — unde e capacitatea acum?" h={300}>
        <ResponsiveContainer>
          <PieChart>
            <Pie data={leveragePie.filter(r=>r.value>0)} dataKey="value" nameKey="name" cx="50%" cy="50%" innerRadius={45} outerRadius={95}
              label={({name,value})=>name.split('(')[0].trim()+': '+fmt(value)+'t'} style={{fontSize:10}}>
              {leveragePie.map((_,i)=><Cell key={i} fill={levColors[i]}/>)}
            </Pie>
            <Tooltip contentStyle={ttStyle} itemStyle={ttItem} labelStyle={ttLabel} formatter={v=>fmt(v)+' t'}/>
          </PieChart>
        </ResponsiveContainer>
      </ChartCard>
    </div>

    {/* Categorii expandabile */}
    <div className="card tbl-card">
      <div className="tbl-head"><span className="tbl-title">Capacitate în port per categorie (click pentru detalii)</span></div>
      <div className="tbl-wrap"><table>
        <thead><tr><th>Categorie</th><th>Nave</th><th>Capacitate (t)</th><th></th></tr></thead>
        <tbody>{data.inPort.map((cat,ci)=><React.Fragment key={ci}>
          <tr onClick={()=>setExpandCat(expandCat===cat.categorie?null:cat.categorie)} style={{cursor:'pointer',background:expandCat===cat.categorie?'rgba(14,165,233,0.08)':''}}>
            <td style={{fontWeight:600,color:capColors[cat.categorie]||'#e2e8f0'}}>{expandCat===cat.categorie?'▼':'▶'} {cat.categorie}</td>
            <td>{cat.cnt}</td>
            <td>{fmt(cat.cap)} t</td>
            <td style={{fontSize:11,color:'#64748b'}}>{data.inPortTotal?.cap>0?Math.round(cat.cap/data.inPortTotal.cap*100):0}% din total</td>
          </tr>
          {expandCat===cat.categorie && cat.vessels.map((v,vi)=><tr key={vi} style={{fontSize:12,background:'rgba(14,165,233,0.03)'}}>
            <td style={{paddingLeft:30,color:'#94a3b8'}}>↳ {v.nava||v.escala||'—'}</td>
            <td style={{fontSize:11}}>{v.owner_text||v.armator||'—'}</td>
            <td>{fmt(v.capacitate_max||v.cantitate||0)} t</td>
            <td style={{fontSize:10,color:'#64748b'}}>{v.marfa?v.marfa+' · ':''}
              {v.provenienta?v.provenienta+'→':''}
              {v.destinatie||''}</td>
          </tr>)}
        </React.Fragment>)}</tbody>
      </table></div>
    </div>

    {/* Convoaie care vin */}
    {data.arrivingDetail?.length>0 && <div className="card tbl-card" style={{marginTop:16}}>
      <div className="tbl-head"><span className="tbl-title">Convoaie avizate sosire ({data.arriving?.convoys} convoaie, {fmt(capArr)} t)</span></div>
      <div className="tbl-wrap"><table>
        <thead><tr><th>Convoi</th><th>Navă</th><th>Armator</th><th>Agent</th><th>HP</th><th>ETA</th></tr></thead>
        <tbody>{data.arrivingDetail.map((r,i)=><tr key={i}>
          <td>{r.convoi}</td>
          <td style={{fontWeight:600,color:'#e2e8f0'}}>{r.nava||'—'}</td>
          <td style={{fontSize:11}}>{r.armator||'—'}</td>
          <td>{r.agent||'—'}</td>
          <td>{r.hp||'—'}</td>
          <td>{fmtDate(r.eta)||'—'}</td>
        </tr>)}</tbody>
      </table></div>
    </div>}

    {/* Convoaie care pleacă + barjele cu marfă */}
    {data.departingBarges?.length>0 && <div className="card tbl-card" style={{marginTop:16}}>
      <div className="tbl-head"><span className="tbl-title">Pleacă din CTA — barje încărcate ({data.departing?.barges} barje, {fmt(capDep)} t)</span></div>
      <div className="tbl-wrap"><table>
        <thead><tr><th>Convoi</th><th>Barjă</th><th>Marfă</th><th>Tone</th><th>Destinație</th></tr></thead>
        <tbody>{data.departingBarges.map((r,i)=><tr key={i}>
          <td>{r.convoi}</td>
          <td style={{fontWeight:600}}>{r.nava||'—'}</td>
          <td>{r.cargo||'—'}</td>
          <td>{fmt(r.cantitate_tone)}</td>
          <td>{r.destinatie||'—'}</td>
        </tr>)}</tbody>
      </table></div>
    </div>}
  </div>;
}

// ═══════════════════════════════════════════════
// PORT PRESENCE PAGE — Analiză prezență nave fluviale în port
// ═══════════════════════════════════════════════
function PortPresencePage({f}) {
  const [daily,setDaily]=useState([]);
  const [cargo,setCargo]=useState(null);
  const [byOp,setByOp]=useState(null);
  const [byAg,setByAg]=useState(null);
  const [cargoTrend,setCargoTrend]=useState([]);
  const [lineup,setLineup]=useState(null);
  const [selOp,setSelOp]=useState('');
  const sortLU = useSortable(lineup?.rows);
  const [byArm,setByArm]=useState([]);
  const [tab,setTab]=useState('overview');

  useEffect(()=>{
    api('/port-presence/daily?'+fQ(f)).then(d=>setDaily(d||[]));
    api('/port-presence/cargo-status?'+fQ(f)).then(setCargo);
    api('/port-presence/by-operator?'+fQ(f)).then(setByOp);
    api('/port-presence/by-agent?'+fQ(f)).then(setByAg);
    api('/port-presence/cargo-trend?'+fQ(f)).then(d=>setCargoTrend(d||[]));
    api('/port-presence/by-armator?'+fQ(f)).then(d=>setByArm(d||[]));
  },[f.days,f.start,f.end,f.date,f.port]);

  useEffect(()=>{
    api('/port-presence/lineup?operator='+encodeURIComponent(selOp)).then(setLineup);
  },[selOp]);

  // Build stacked cargo trend — aggregate weekly when >30 days
  const cargoNames = [...new Set(cargoTrend.map(r=>r.marfa))].slice(0,8);
  const numDays = f.mode==='day' ? 1 : f.mode==='custom'&&f.start&&f.end ? Math.ceil((new Date(f.end)-new Date(f.start))/86400000) : Number(f.days||30);
  const useWeekly = numDays > 30;
  const cargoMap = {};
  cargoTrend.forEach(r=>{
    let key;
    if(useWeekly) {
      const d = new Date(r.date);
      const mon = d.toLocaleDateString('ro-RO',{day:'2-digit',month:'short'});
      const dayOfWeek = d.getDay();
      const weekStart = new Date(d); weekStart.setDate(d.getDate() - dayOfWeek + 1);
      key = 'S' + weekStart.toLocaleDateString('ro-RO',{day:'2-digit',month:'short'});
    } else {
      key = fmtDate(r.date);
    }
    if(!cargoMap[key]) cargoMap[key]={date:key};
    cargoMap[key][r.marfa]=(cargoMap[key][r.marfa]||0)+Number(r.tone);
  });
  const cargoStackData = Object.values(cargoMap);

  const tabs = [['overview','Prezență'],['lineup','Line-Up Operator']];

  return <div className="page-content">
    <div className="section-header">
      <h2>Prezență Nave Fluviale în Port</h2>
      <p>Analiză zilnică nave în port, goale/pline, per operator, per agent, distribuție marfă</p>
    </div>
    <div style={{display:'flex',gap:6,marginBottom:16}}>
      {tabs.map(([k,l])=><button key={k} className={'btn-sm'+(tab===k?' active':'')} onClick={()=>setTab(k)}>{l}</button>)}
    </div>

    {tab==='overview'&&<>
      {/* Chart 1: Nave totale + tip per zi */}
      <ChartCard title="Nave fluviale în port / zi (total + tip)">
        {daily.length===0?<div className="empty">Nu sunt date</div>:
        <ResponsiveContainer>
          <AreaChart data={daily.map(r=>({...r,date:fmtDate(r.date)}))}>
            <CartesianGrid strokeDasharray="3 3" stroke="#1e293b"/>
            <XAxis dataKey="date" tick={{fill:'#64748b',fontSize:10}} angle={-20} textAnchor="end" height={40}/>
            <YAxis tick={{fill:'#64748b',fontSize:11}}/>
            <Tooltip contentStyle={ttStyle} itemStyle={ttItem} labelStyle={ttLabel}/>
            <Area type="monotone" dataKey="barje" stackId="1" stroke="#0ea5e9" fill="#0ea5e9" fillOpacity={0.4} name="Barje"/>
            <Area type="monotone" dataKey="autopropulsate" stackId="1" stroke="#10b981" fill="#10b981" fillOpacity={0.4} name="Autopropulsate"/>
            <Area type="monotone" dataKey="tankuri" stackId="1" stroke="#f59e0b" fill="#f59e0b" fillOpacity={0.4} name="Tankuri"/>
            <Legend/>
          </AreaChart>
        </ResponsiveContainer>}
      </ChartCard>

      <div className="grid-2">
        {/* Chart 2: Goale vs Pline per zi */}
        <ChartCard title="Nave goale vs încărcate / zi">
          {!cargo||!cargo.daily?.length?<div className="empty">Nu sunt date</div>:
          <ResponsiveContainer>
            <AreaChart data={cargo.daily.map(r=>({...r,date:fmtDate(r.date)}))}>
              <CartesianGrid strokeDasharray="3 3" stroke="#1e293b"/>
              <XAxis dataKey="date" tick={{fill:'#64748b',fontSize:10}} angle={-20} textAnchor="end" height={40}/>
              <YAxis tick={{fill:'#64748b',fontSize:11}}/>
              <Tooltip contentStyle={ttStyle} itemStyle={ttItem} labelStyle={ttLabel}/>
              <Area type="monotone" dataKey="pline" stroke="#10b981" fill="#10b981" fillOpacity={0.3} name="Încărcate"/>
              <Area type="monotone" dataKey="goale" stroke="#ef4444" fill="#ef4444" fillOpacity={0.3} name="Goale"/>
              <Legend/>
            </AreaChart>
          </ResponsiveContainer>}
        </ChartCard>

        {/* Chart 3: Marfă snapshot (pie) */}
        <ChartCard title="Distribuție marfă în port (snapshot)">
          {!cargo||!cargo.cargoSnap?.length?<div className="empty">Nu sunt date</div>:
          <ResponsiveContainer>
            <PieChart>
              <Pie data={cargo.cargoSnap.slice(0,10)} dataKey="tone" nameKey="marfa" cx="50%" cy="50%" innerRadius={40} outerRadius={90}
                label={({marfa,percent,x,y,cx})=>percent>0.05?<text x={x} y={y} fill="#e2e8f0" fontSize={10} textAnchor={x>cx?'start':'end'} dominantBaseline="central">{marfa?.substring(0,14)}</text>:null} labelLine={{stroke:'#64748b'}}>
                {cargo.cargoSnap.slice(0,10).map((_,i)=><Cell key={i} fill={COLORS[i%COLORS.length]}/>)}
              </Pie>
              <Tooltip contentStyle={ttStyle} itemStyle={ttItem} labelStyle={ttLabel} formatter={v=>fmt(v)+' t'}/>
              <Legend wrapperStyle={{fontSize:10,color:'#94a3b8'}}/>
            </PieChart>
          </ResponsiveContainer>}
        </ChartCard>
      </div>

      <div className="grid-2">
        {/* Chart 4: Per operator */}
        <ChartCard title="Nave per operator portuar (snapshot)">
          {!byOp||!byOp.rows?.length?<div className="empty">Nu sunt date</div>:
          <ResponsiveContainer>
            <BarChart data={byOp.rows.slice(0,12)} layout="vertical">
              <CartesianGrid strokeDasharray="3 3" stroke="#1e293b"/>
              <XAxis type="number" tick={{fill:'#64748b',fontSize:11}}/>
              <YAxis dataKey="operator_name" type="category" width={120} tick={{fill:'#94a3b8',fontSize:10}}/>
              <Tooltip contentStyle={ttStyle} itemStyle={ttItem} labelStyle={ttLabel}/>
              <Bar dataKey="nave" fill="#8b5cf6" radius={[0,4,4,0]} name="Nave"/>
            </BarChart>
          </ResponsiveContainer>}
        </ChartCard>

        {/* Chart 5: Per agent */}
        <ChartCard title="Nave per agent (snapshot)">
          {!byAg||!byAg.rows?.length?<div className="empty">Nu sunt date</div>:
          <ResponsiveContainer>
            <BarChart data={byAg.rows.slice(0,12)} layout="vertical">
              <CartesianGrid strokeDasharray="3 3" stroke="#1e293b"/>
              <XAxis type="number" tick={{fill:'#64748b',fontSize:11}}/>
              <YAxis dataKey="agent_name" type="category" width={120} tick={{fill:'#94a3b8',fontSize:10}}/>
              <Tooltip contentStyle={ttStyle} itemStyle={ttItem} labelStyle={ttLabel}/>
              <Bar dataKey="nave" fill="#06b6d4" radius={[0,4,4,0]} name="Nave"/>
            </BarChart>
          </ResponsiveContainer>}
        </ChartCard>
      </div>

      {/* Chart 6: Stacked bar — marfa × zile/săptămâni */}
      <ChartCard title={`Distribuție marfă (tone) / ${useWeekly?'săptămână':'zi'} — Stacked${useWeekly?' (agregat săptămânal)':''}`}>
        {cargoStackData.length===0?<div className="empty">Nu sunt date de marfă pentru perioada selectată</div>:
        <ResponsiveContainer>
          <BarChart data={cargoStackData} barCategoryGap={cargoStackData.length<10?"20%":"5%"}>
            <CartesianGrid strokeDasharray="3 3" stroke="#1e293b"/>
            <XAxis dataKey="date" tick={{fill:'#64748b',fontSize:9}} angle={-20} textAnchor="end" height={45}/>
            <YAxis tick={{fill:'#64748b',fontSize:11}}/>
            <Tooltip contentStyle={ttStyle} itemStyle={ttItem} labelStyle={ttLabel} formatter={v=>fmt(v)+' t'}/>
            {cargoNames.map((m,i)=><Bar key={m} dataKey={m} stackId="a" fill={COLORS[i%COLORS.length]} maxBarSize={80}/>)}
            <Legend wrapperStyle={{fontSize:10}} formatter={(v)=>v.length>25?v.substring(0,22)+'…':v}/>
          </BarChart>
        </ResponsiveContainer>}
      </ChartCard>

      {/* Armatori — distinct nave */}
      <ChartCard title="Nave distincte per armator (perioadă)">
        {byArm.length===0?<div className="empty">Nu sunt date</div>:
        <ResponsiveContainer>
          <BarChart data={byArm.slice(0,15)} layout="vertical">
            <CartesianGrid strokeDasharray="3 3" stroke="#1e293b"/>
            <XAxis type="number" tick={{fill:'#64748b',fontSize:11}}/>
            <YAxis dataKey="armator" type="category" width={140} tick={{fill:'#94a3b8',fontSize:9}}/>
            <Tooltip contentStyle={ttStyle} itemStyle={ttItem} labelStyle={ttLabel}/>
            <Bar dataKey="nave_distincte" fill="#f59e0b" radius={[0,4,4,0]} name="Nave distincte"/>
          </BarChart>
        </ResponsiveContainer>}
      </ChartCard>
    </>}

    {tab==='lineup'&&<>
      <div style={{marginBottom:12,display:'flex',alignItems:'center',gap:10,flexWrap:'wrap'}}>
        <span style={{color:'#94a3b8',fontSize:12}}>Selectează operator:</span>
        <select value={selOp} onChange={e=>setSelOp(e.target.value)} style={{padding:'6px 12px',background:'#0a0e17',border:'1px solid #1e293b',borderRadius:6,color:'#e2e8f0',fontSize:13}}>
          <option value="">— Toți operatorii —</option>
          {(lineup?.operators||[]).map(o=><option key={o.cod} value={o.cod}>{o.name} ({o.cnt})</option>)}
        </select>
        {lineup&&<span style={{color:'#64748b',fontSize:12}}>{lineup.total} nave · Snapshot {fmtDate(lineup.snapshot)}</span>}
      </div>

      {/* KPI Cards */}
      {(()=>{
        const lr = lineup?.rows||[];
        const pline = lr.filter(r=>Number(r.cantitate_rest||0)>0);
        const goale = lr.filter(r=>Number(r.cantitate_rest||0)===0);
        const totalTone = lr.reduce((s,r)=>s+Number(r.cantitate_rest||0),0);
        const avgZile = lr.length>0?Math.round(lr.reduce((s,r)=>s+Number(r.zile_stationare||0),0)/lr.length):0;
        const over20 = lr.filter(r=>Number(r.zile_stationare||0)>20).length;

        // Cargo type breakdown
        const cargoMap = {};
        lr.forEach(r=>{const m=r.marfa||'Goale/Nespecificat'; cargoMap[m]=(cargoMap[m]||0)+1;});
        const cargoPie = Object.entries(cargoMap).map(([k,v])=>({marfa:k,cnt:v})).sort((a,b)=>b.cnt-a.cnt).slice(0,8);

        // Days distribution
        const daysBuckets = [{label:'0-5z',min:0,max:5,color:'#10b981'},{label:'6-10z',min:6,max:10,color:'#06b6d4'},
          {label:'11-20z',min:11,max:20,color:'#f59e0b'},{label:'21-30z',min:21,max:30,color:'#ef4444'},{label:'>30z',min:31,max:9999,color:'#dc2626'}];
        const daysData = daysBuckets.map(b=>({...b,cnt:lr.filter(r=>{const z=Number(r.zile_stationare||0);return z>=b.min&&z<=b.max;}).length}));

        return <>
          <div className="kpi-grid" style={{gridTemplateColumns:'repeat(5,1fr)'}}>
            <Kpi label="Total nave" value={lr.length} hint={selOp?(lineup?.operators||[]).find(o=>o.cod===selOp)?.name||selOp:'toți operatorii'} color="#0ea5e9"/>
            <Kpi label="Pline (cu marfă)" value={pline.length} hint={fmt(totalTone)+' t rest'} color="#10b981"/>
            <Kpi label="Goale" value={goale.length} hint={Math.round(goale.length/Math.max(lr.length,1)*100)+'%'} color="#ef4444"/>
            <Kpi label="Media stationare" value={avgZile+'z'} hint={over20+' nave >20 zile'} color="#f59e0b"/>
            <Kpi label="Tipuri marfă" value={Object.keys(cargoMap).length} hint="distincte" color="#8b5cf6"/>
          </div>

          <div className="grid-2">
            {/* Cargo type pie */}
            <ChartCard title="Distribuție per tip marfă (nave)" h={250}>
              {cargoPie.length===0?<div className="empty">Nu sunt date</div>:
              <ResponsiveContainer>
                <PieChart>
                  <Pie data={cargoPie} dataKey="cnt" nameKey="marfa" cx="50%" cy="50%" innerRadius={35} outerRadius={80}
                    label={({marfa,percent})=>percent>0.06?marfa?.substring(0,12):''}
                    style={{fontSize:10}}>
                    {cargoPie.map((_,i)=><Cell key={i} fill={COLORS[i%COLORS.length]} stroke="none"/>)}
                  </Pie>
                  <Tooltip contentStyle={ttStyle} itemStyle={ttItem} labelStyle={ttLabel}/>
                  <Legend wrapperStyle={{fontSize:10}} formatter={v=>v.length>20?v.substring(0,18)+'…':v}/>
                </PieChart>
              </ResponsiveContainer>}
            </ChartCard>

            {/* Days distribution bar */}
            <ChartCard title="Distribuție zile stationare" h={250}>
              <ResponsiveContainer>
                <BarChart data={daysData}>
                  <CartesianGrid strokeDasharray="3 3" stroke="#1e293b"/>
                  <XAxis dataKey="label" tick={{fill:'#94a3b8',fontSize:11}}/>
                  <YAxis tick={{fill:'#64748b',fontSize:11}}/>
                  <Tooltip contentStyle={ttStyle} itemStyle={ttItem} labelStyle={ttLabel}/>
                  <Bar dataKey="cnt" name="Nave" radius={[4,4,0,0]}>
                    {daysData.map((d,i)=><Cell key={i} fill={d.color}/>)}
                  </Bar>
                </BarChart>
              </ResponsiveContainer>
            </ChartCard>
          </div>

          {/* Full vs Empty bar per operator (when showing all) */}
          {!selOp && lr.length>0 && <ChartCard title="Pline vs Goale per operator" h={Math.max(200, (lineup?.operators||[]).length*25)}>
            <ResponsiveContainer>
              <BarChart data={(lineup?.operators||[]).slice(0,15).map(op=>{
                const opRows = lr.filter(r=>r.operator===op.cod);
                return {name:op.name||op.cod, pline:opRows.filter(r=>Number(r.cantitate_rest||0)>0).length, goale:opRows.filter(r=>Number(r.cantitate_rest||0)===0).length};
              })} layout="vertical">
                <CartesianGrid strokeDasharray="3 3" stroke="#1e293b"/>
                <XAxis type="number" tick={{fill:'#64748b',fontSize:11}}/>
                <YAxis dataKey="name" type="category" width={120} tick={{fill:'#94a3b8',fontSize:9}}/>
                <Tooltip contentStyle={ttStyle} itemStyle={ttItem} labelStyle={ttLabel}/>
                <Legend/>
                <Bar dataKey="pline" stackId="a" fill="#10b981" name="Pline"/>
                <Bar dataKey="goale" stackId="a" fill="#ef4444" name="Goale"/>
              </BarChart>
            </ResponsiveContainer>
          </ChartCard>}
        </>;
      })()}

      {/* Table with sortable headers */}
      <div className="card">
        <div className="tbl-head"><span className="tbl-title">Line-Up {selOp?('— '+((lineup?.operators||[]).find(o=>o.cod===selOp)?.name||selOp)):'— Toți operatorii'} ({lineup?.total||0})</span></div>
        <div style={{maxHeight:600,overflow:'auto'}}>
        <table><thead><tr><th>#</th>
          <th {...sortLU.thProps('nava')}>Navă{sortLU.arrow('nava')}</th>
          <th {...sortLU.thProps('armator')}>Armator{sortLU.arrow('armator')}</th>
          <th {...sortLU.thProps('agent')}>Agent{sortLU.arrow('agent')}</th>
          <th {...sortLU.thProps('operator_name')}>Operator{sortLU.arrow('operator_name')}</th>
          <th {...sortLU.thProps('marfa')}>Marfă{sortLU.arrow('marfa')}</th>
          <th {...sortLU.thProps('cantitate_rest')}>Rest (t){sortLU.arrow('cantitate_rest')}</th>
          <th {...sortLU.thProps('provenienta')}>Proveniență{sortLU.arrow('provenienta')}</th>
          <th {...sortLU.thProps('destinatie')}>Destinație{sortLU.arrow('destinatie')}</th>
          <th {...sortLU.thProps('dana')}>Dana{sortLU.arrow('dana')}</th>
          <th {...sortLU.thProps('rta')}>Sosire{sortLU.arrow('rta')}</th>
          <th {...sortLU.thProps('zile_stationare')}>Zile{sortLU.arrow('zile_stationare')}</th>
        </tr></thead><tbody>
        {sortLU.sorted.map((r,i)=><tr key={i} style={r.zile_stationare>20?{background:'rgba(239,68,68,.08)'}:r.zile_stationare>10?{background:'rgba(245,158,11,.06)'}:{}}>
          <td>{i+1}</td>
          <td style={{fontWeight:600,color:'#e2e8f0'}}>{r.nava}</td>
          <td style={{fontSize:11}}>{r.armator||'—'}</td><td>{r.agent||'—'}</td>
          <td style={{fontSize:11}}>{r.operator_name||r.operator||'—'}</td>
          <td>{r.marfa||<span style={{color:'#64748b'}}>Goală</span>}</td>
          <td style={{textAlign:'right',fontWeight:500,color:Number(r.cantitate_rest||0)>0?'#10b981':'#64748b'}}>{fmt(r.cantitate_rest)}</td>
          <td style={{fontSize:11}}>{r.provenienta||'—'}</td><td style={{fontSize:11}}>{r.destinatie||'—'}</td>
          <td>{r.dana||'—'}</td>
          <td style={{fontSize:11}}>{r.rta?fmtDate(r.rta):'—'}</td>
          <td style={{textAlign:'right',fontWeight:600,color:r.zile_stationare>20?'#ef4444':r.zile_stationare>10?'#f59e0b':'#10b981'}}>{r.zile_stationare??'—'}z</td>
        </tr>)}
        {sortLU.sorted.length===0&&<tr><td colSpan={12} className="empty">Nu sunt nave pentru operatorul selectat</td></tr>}
        </tbody></table>
        </div>
      </div>
    </>}
  </div>;
}

// ═══════════════════════════════════════════════
// HELP PAGE — Documentație meniuri (CEO only)
// ═══════════════════════════════════════════════
// ═══════════════════════════════════════════════
// PORT MAP — Interactive Leaflet Map + AIS Live
// ═══════════════════════════════════════════════
function PortMapPage() {
  const mapRef = useRef(null);
  const mapInstanceRef = useRef(null);
  const layersRef = useRef({});
  const aisLayerRef = useRef(null);
  const [stats,setStats]=useState(null);
  const [aisStats,setAisStats]=useState(null);
  const [loading,setLoading]=useState(true);
  const [source,setSource]=useState('buletine'); // 'buletine' or 'ais'
  const [layers,setLayers]=useState({dane:true,pontoane:true,terminale:true,fluvial:true,maritim:true,blocat:true,rada:true});

  const VESSEL_COLORS = {fluvial:'#0ea5e9',maritim:'#f59e0b',blocat:'#ef4444',rada:'#8b5cf6'};
  const ZONE_COLORS = {dane:'#334155',pontoane:'#1e40af',terminale_bunker:'#b45309',roro:'#047857',
    socep:'#6d28d9',decirom:'#be185d',scs:'#0369a1',golf:'#475569',rkf:'#dc2626',
    sno:'#4338ca',pushers:'#0f766e',dane_speciale:'#64748b',boundary:'#1e293b44'};

  useEffect(()=>{
    if(!mapRef.current || mapInstanceRef.current) return;
    const L = window.L;
    if(!L) return;

    const map = L.map(mapRef.current, {
      center: [44.14, 28.66], zoom: 13,
      zoomControl: true, attributionControl: false
    });
    mapInstanceRef.current = map;

    const sat = L.tileLayer('https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}', {maxZoom:19});
    const osm = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {maxZoom:19});
    sat.addTo(map);
    L.control.layers({'Satelit':sat,'Hartă':osm},null,{position:'topright'}).addTo(map);

    loadGeofences(map, L);
    loadBuletineVessels(map, L);
  },[]);

  // Load geofence polygons (once)
  const loadGeofences = async (map, L) => {
    try {
      const geoData = await api('/port-map/geofences');
      if(!geoData || !geoData.features) { console.warn('Port map: no geofence data'); return; }
      const zoneGroups = {};
    (geoData?.features||[]).forEach(feat => {
      const cat = feat.properties.category;
      const color = ZONE_COLORS[cat] || '#334155';
      const isBoundary = cat === 'boundary';
      const coords = feat.geometry.coordinates[0].map(c=>[c[1],c[0]]);
      const poly = L.polygon(coords, {
        color: isBoundary ? '#475569' : color, weight: isBoundary ? 2 : 1,
        fillColor: color, fillOpacity: isBoundary ? 0.05 : 0.2,
        dashArray: isBoundary ? '8,4' : null
      });
      if(!isBoundary) poly.bindTooltip(feat.properties.name, {permanent:false, className:'map-tooltip', direction:'center'});
      if(!zoneGroups[cat]) zoneGroups[cat] = L.layerGroup();
      zoneGroups[cat].addLayer(poly);
    });
    Object.values(zoneGroups).forEach(g=>g.addTo(map));
    layersRef.current.zones = zoneGroups;
    const boundary = (geoData?.features||[]).find(f=>f.properties.category==='boundary');
    if(boundary) map.fitBounds(boundary.geometry.coordinates[0].map(c=>[c[1],c[0]]), {padding:[20,20]});
    } catch(e) { console.error('Port map geofences error:', e); }
  };

  // Load bulletin-based vessel positions
  const loadBuletineVessels = async (map, L) => {
    try {
      const vesselData = await api('/port-map/vessels');
      if(!vesselData || !vesselData.vessels) { console.warn('Port map: no vessel data'); setLoading(false); return; }
      setStats(vesselData.stats);
      const vesselGroups = {};
      vesselData.vessels.forEach(v => {
        if(!v.lat || !v.lng) return;
        const color = VESSEL_COLORS[v.type]||'#64748b';
        const circle = L.circleMarker([v.lat, v.lng], {
          radius: v.type==='maritim'?8:v.type==='rada'?6:5,
          color, fillColor:color, fillOpacity:0.8, weight:1.5
        });
        const popupHtml = buildPopup(v);
        circle.bindPopup(popupHtml, {maxWidth:300});
        circle.bindTooltip(v.nava||'?', {permanent:false, className:'map-tooltip'});
        if(!vesselGroups[v.type]) vesselGroups[v.type] = L.layerGroup();
        vesselGroups[v.type].addLayer(circle);
      });
      Object.values(vesselGroups).forEach(g=>g.addTo(map));
      layersRef.current.vessels = vesselGroups;
      console.log('Port map loaded:', vesselData.vessels.length, 'vessels,', Object.keys(vesselGroups).length, 'types');
    } catch(e) { console.error('Port map vessels error:', e); }
    setLoading(false);
  };

  // Load AIS live positions
  const loadAIS = async () => {
    const map = mapInstanceRef.current;
    const L = window.L;
    if(!map || !L) return;
    const data = await api('/port-map/ais-positions');
    setAisStats(data);

    // Remove old AIS layer
    if(aisLayerRef.current) { map.removeLayer(aisLayerRef.current); }
    const aisGroup = L.layerGroup();

    (data?.vessels||[]).forEach(v => {
      if(!v.lat || !v.lng) return;
      const isMatched = v.matched;
      const color = isMatched ? '#10b981' : '#f97316';
      const name = v.nave_master_name || v.ship_name || v.mmsi;
      
      // Triangle marker for AIS (shows heading)
      const marker = L.circleMarker([v.lat, v.lng], {
        radius: isMatched ? 7 : 5,
        color: '#ffffff', weight: 2,
        fillColor: color, fillOpacity: 0.9
      });
      
      const speed = v.speed != null ? (v.speed/10).toFixed(1) : '?';
      const popupHtml = `<div style="font-family:Inter,system-ui,sans-serif;font-size:12px;min-width:200px">
        <div style="font-weight:700;font-size:14px;margin-bottom:2px;color:#0f172a">${name}</div>
        <div style="color:#64748b;font-size:10px;margin-bottom:6px">
          MMSI: ${v.mmsi} · AIS LIVE ${isMatched?'✅ Identificat':'⚠️ Necunoscut'}
        </div>
        <table style="width:100%;font-size:11px">
        <tr><td style="color:#64748b;padding:2px 6px 2px 0">Viteză</td><td>${speed} kn</td></tr>
        <tr><td style="color:#64748b;padding:2px 6px 2px 0">Curs</td><td>${v.course!=null?(v.course/10).toFixed(0)+'°':'?'}</td></tr>
        <tr><td style="color:#64748b;padding:2px 6px 2px 0">Heading</td><td>${v.heading||'?'}°</td></tr>
        ${v.tip_nava?`<tr><td style="color:#64748b;padding:2px 6px 2px 0">Tip</td><td>${v.tip_nava}</td></tr>`:''}
        ${v.tip_navigatie?`<tr><td style="color:#64748b;padding:2px 6px 2px 0">Nav</td><td>${v.tip_navigatie}</td></tr>`:''}
        ${v.pavilion?`<tr><td style="color:#64748b;padding:2px 6px 2px 0">Pavilion</td><td>${v.pavilion}</td></tr>`:''}
        ${v.owner?`<tr><td style="color:#64748b;padding:2px 6px 2px 0">Owner</td><td style="font-size:10px">${v.owner}</td></tr>`:''}
        <tr><td style="color:#64748b;padding:2px 6px 2px 0">Update</td><td style="font-size:10px">${v.ts?new Date(v.ts).toLocaleTimeString('ro-RO'):''}</td></tr>
        </table>
      </div>`;
      marker.bindPopup(popupHtml, {maxWidth:300});
      marker.bindTooltip(name, {permanent:false, className:'map-tooltip'});
      aisGroup.addLayer(marker);
    });
    aisGroup.addTo(map);
    aisLayerRef.current = aisGroup;
  };

  // Switch source
  useEffect(()=>{
    const map = mapInstanceRef.current;
    if(!map) return;
    if(source==='ais') {
      // Hide bulletin vessels, show AIS
      Object.values(layersRef.current.vessels||{}).forEach(g=>map.removeLayer(g));
      loadAIS();
    } else {
      // Hide AIS, show bulletin vessels
      if(aisLayerRef.current) map.removeLayer(aisLayerRef.current);
      Object.values(layersRef.current.vessels||{}).forEach(g=>g.addTo(map));
    }
  },[source]);

  // Auto-refresh AIS every 30s
  useEffect(()=>{
    if(source!=='ais') return;
    const interval = setInterval(loadAIS, 30000);
    return ()=>clearInterval(interval);
  },[source]);

  function buildPopup(v) {
    return `<div style="font-family:Inter,system-ui,sans-serif;font-size:12px;min-width:200px">
      <div style="font-weight:700;font-size:14px;margin-bottom:4px;color:#0f172a">${v.nava||'—'}</div>
      <div style="color:#64748b;font-size:11px;margin-bottom:6px">${(v.type||'').toUpperCase()} · ${v.dana||'N/A'}</div>
      <table style="width:100%;font-size:11px;border-collapse:collapse">
      ${v.marfa?`<tr><td style="color:#64748b;padding:2px 6px 2px 0">Marfă</td><td style="font-weight:500">${v.marfa}</td></tr>`:''}
      ${v.cantitate?`<tr><td style="color:#64748b;padding:2px 6px 2px 0">Cantitate</td><td>${fmt(v.cantitate)} t</td></tr>`:''}
      ${v.rest?`<tr><td style="color:#64748b;padding:2px 6px 2px 0">Rest</td><td style="color:#ef4444;font-weight:600">${fmt(v.rest)} t</td></tr>`:''}
      ${v.operator?`<tr><td style="color:#64748b;padding:2px 6px 2px 0">Operator</td><td>${v.operator}</td></tr>`:''}
      ${v.agent?`<tr><td style="color:#64748b;padding:2px 6px 2px 0">Agent</td><td>${v.agent}</td></tr>`:''}
      ${v.armator?`<tr><td style="color:#64748b;padding:2px 6px 2px 0">Armator</td><td>${v.armator}</td></tr>`:''}
      ${v.zile_port!=null?`<tr><td style="color:#64748b;padding:2px 6px 2px 0">Zile port</td><td style="font-weight:600;color:${v.zile_port>20?'#ef4444':v.zile_port>10?'#f59e0b':'#10b981'}">${v.zile_port}z</td></tr>`:''}
      ${v.motiv?`<tr><td style="color:#64748b;padding:2px 6px 2px 0">Blocare</td><td style="color:#ef4444">${v.motiv}</td></tr>`:''}
      </table></div>`;
  }

  const toggleLayer = (key) => {
    const map = mapInstanceRef.current;
    if(!map) return;
    const newState = !layers[key];
    setLayers(prev=>({...prev,[key]:newState}));
    if(source==='buletine') {
      const vg = layersRef.current.vessels?.[key];
      if(vg) { newState ? vg.addTo(map) : map.removeLayer(vg); }
    }
    const zg = layersRef.current.zones?.[key];
    if(zg) { newState ? zg.addTo(map) : map.removeLayer(zg); }
  };

  return <div className="page-content" style={{padding:0,height:'calc(100vh - 52px)',display:'flex',flexDirection:'column'}}>
    <div style={{padding:'10px 20px',borderBottom:'1px solid #1e293b',display:'flex',justifyContent:'space-between',alignItems:'center',flexWrap:'wrap',gap:8}}>
      <div>
        <h2 style={{margin:0,fontSize:16}}>Hartă Port Constanța</h2>
        <p style={{margin:0,fontSize:11,color:'#64748b'}}>
          {source==='buletine'
            ? stats?`Buletin · ${stats.fluvial} fluv, ${stats.maritim} marit, ${stats.blocked} blocate, ${stats.rada} radă · ${stats.positioned} poziționate`:'Se încarcă...'
            : aisStats?`AIS Live · ${aisStats.vessels?.length||0} nave detectate · ${aisStats.matched} identificate · ${aisStats.status?.connected?'🟢 Conectat':'🔴 Deconectat'}`:'Se încarcă AIS...'
          }
        </p>
      </div>
      <div style={{display:'flex',gap:6,alignItems:'center'}}>
        {/* Source toggle */}
        <div style={{display:'flex',borderRadius:6,overflow:'hidden',border:'1px solid #334155'}}>
          <button onClick={()=>setSource('buletine')} style={{padding:'4px 12px',fontSize:11,border:'none',cursor:'pointer',fontWeight:600,
            background:source==='buletine'?'#0ea5e9':'transparent',color:source==='buletine'?'#fff':'#64748b'}}>📋 Buletine</button>
          <button onClick={()=>setSource('ais')} style={{padding:'4px 12px',fontSize:11,border:'none',borderLeft:'1px solid #334155',cursor:'pointer',fontWeight:600,
            background:source==='ais'?'#10b981':'transparent',color:source==='ais'?'#fff':'#64748b'}}>📡 AIS Live</button>
        </div>
        {source==='buletine' && <div style={{display:'flex',gap:3}}>
          {Object.entries(VESSEL_COLORS).map(([k,c])=>
            <button key={k} onClick={()=>toggleLayer(k)} style={{
              padding:'2px 8px',fontSize:9,borderRadius:10,border:'1px solid '+c,
              background:layers[k]?c+'33':'transparent',color:layers[k]?c:'#64748b',cursor:'pointer',fontWeight:600
            }}>{k==='blocat'?'Bloc':k==='rada'?'Radă':k.charAt(0).toUpperCase()+k.slice(1)}</button>
          )}
        </div>}
      </div>
    </div>
    <div style={{flex:1,position:'relative'}}>
      {loading && <div style={{position:'absolute',top:'50%',left:'50%',transform:'translate(-50%,-50%)',zIndex:1000,
        background:'#0f172aee',padding:'20px 30px',borderRadius:8,color:'#e2e8f0',fontSize:14}}>Se încarcă harta...</div>}
      <div ref={mapRef} style={{width:'100%',height:'100%'}}/>
    </div>
    {/* Legend */}
    <div style={{position:'absolute',bottom:20,left:280,zIndex:1000,background:'#0f172aee',borderRadius:8,padding:'8px 12px',
      border:'1px solid #1e293b',maxHeight:180,overflowY:'auto',fontSize:10}}>
      <div style={{fontWeight:700,color:'#e2e8f0',marginBottom:4,fontSize:11}}>
        {source==='buletine'?'Buletine':'AIS Live'}
      </div>
      {source==='buletine' ? Object.entries(VESSEL_COLORS).map(([k,c])=>
        <div key={k} style={{display:'flex',alignItems:'center',gap:5,marginBottom:2}}>
          <span style={{width:8,height:8,borderRadius:'50%',background:c,display:'inline-block'}}/>
          <span style={{color:'#94a3b8'}}>{k==='fluvial'?'Fluviale':k==='maritim'?'Maritime op.':k==='blocat'?'Blocate':'Radă'}</span>
        </div>
      ) : <>
        <div style={{display:'flex',alignItems:'center',gap:5,marginBottom:2}}>
          <span style={{width:8,height:8,borderRadius:'50%',background:'#10b981',border:'1px solid #fff',display:'inline-block'}}/>
          <span style={{color:'#94a3b8'}}>Identificat (nave_master)</span>
        </div>
        <div style={{display:'flex',alignItems:'center',gap:5,marginBottom:2}}>
          <span style={{width:8,height:8,borderRadius:'50%',background:'#f97316',border:'1px solid #fff',display:'inline-block'}}/>
          <span style={{color:'#94a3b8'}}>Necunoscut (fără MMSI match)</span>
        </div>
        <div style={{color:'#64748b',fontSize:9,marginTop:3}}>Auto-refresh: 30s</div>
      </>}
    </div>
  </div>;
}

function HelpPage() {
  const menus = [
    {id:'dash',label:'Dashboard',access:'CEO, Commercial, Operations',
      desc:'Pagina principală — snapshot KPI-uri pentru ziua curentă, trend tone/zi (fluvial + maritim), distribuție marfă (pie chart), top agenți și top operatori portuari.',
      data:'Endpoint-uri: /api/snapshot (KPI), /api/trend (grafic), /api/top-agents, /api/top-cargo, /api/top-operators. Surse DB: fl_af_sosire, fl_af_plecare, fl_nfip, mt_nso, mt_nr, mt_nfop, mt_am.'},
    {id:'agency',label:'Port Agency',access:'CEO, Commercial, Operations',
      desc:'Oportunități de agenturare. Maritime: nave avizate + în radă + fără agent (oportunitate). Fluviale: convoaie sosire cu detalii barje, agenți, armatori. Link VesselFinder pe fiecare navă.',
      data:'Endpoint-uri: /api/agency-arrivals (mt_am + mt_nr), /api/agency-stats (mt_am), /api/agency-fluvial (fl_af_sosire), /api/agency-fluvial-stats.'},
    {id:'comm',label:'Commercial',access:'CEO, Commercial',
      desc:'Rute comerciale (proveniență → destinație), top armatori pe volum, top marfă. Identificare coridoare active și tendințe.',
      data:'Endpoint-uri: /api/routes (fl_af_sosire + fl_af_plecare), /api/top-armatori (fl_af_sosire), /api/top-cargo (fl_nfip + mt_nso + mt_nr).'},
    {id:'armatori',label:'Armatori',access:'CEO, Commercial',
      desc:'Analiza detaliată a armatorilor: volum pe marfă (stacked bar), topul armatorilor pe cantitate transportată.',
      data:'Endpoint-uri: /api/top-armatori, /api/armator-marfa. Surse: fl_af_sosire deduplicated.'},
    {id:'convoaie',label:'Convoaie',access:'CEO, Commercial, Operations',
      desc:'Convoaie avizate sosire: cap convoi, barje, cantitate, marfă, proveniență, destinație. Util pentru planificarea operațiunilor.',
      data:'Endpoint: /api/convoaie. Sursa: fl_af_sosire (grupat pe convoi).'},
    {id:'ops',label:'Operare',access:'CEO, Operations',
      desc:'Nave maritime sub operare (mt_nso) cu rest de descărcat/încărcat. Blocaje maritime (mt_nfop) — nave fără operațiuni.',
      data:'Endpoint-uri: /api/ops-active (mt_nso), /api/blockers (mt_nfop).'},
    {id:'bunker',label:'Lichide',access:'CEO, Commercial, Operations',
      desc:'Combustibili și produse lichide: motorină, benzină, benzen, ulei. Maritime (tankuri sub operare) + fluviale (plecări cu combustibil). Destinații și volume.',
      data:'Endpoint: /api/lichide. Surse: mt_nso (filtrat pe cargo lichid + nave_master tip TANK), fl_af_plecare (filtrat pe cargo combustibil).'},
    {id:'naveflu',label:'Nave Fluv. Port',access:'CEO, Commercial, Operations',
      desc:'Nave fluviale prezente în port Constanța. Grupare pe armatori, taxare portuară APC (tarife pe zile stationare), detalii per navă.',
      data:'Endpoint: /api/nfip-port-dues. Sursa: fl_nfip (snapshot zi curentă) + nave_master.'},
    {id:'portpres',label:'Prezență Port',access:'CEO, Commercial, Operations',
      desc:'Analiză extinsă prezență nave: trend zilnic pe tip (barje/autopropulsate/tankuri), goale vs încărcate, distribuție per operator/agent, stacked bar marfă/zi. TAB Line-Up: selectare operator → tabel ordonat cronologic (cea mai veche sosire → cea mai nouă), cu zile stationare colorate.',
      data:'Endpoint-uri: /api/port-presence/daily, cargo-status, by-operator, by-agent, cargo-trend, lineup, by-armator. Sursa: fl_nfip + nave_master + operatori_master + agenti_master.'},
    {id:'fleet',label:'Fleet Intel',access:'CEO, Commercial',
      desc:'Intelligence flotă: pie active/inactive/dispărute, categorii nave (tip_nava), lista detaliată cu filtre pe navigație și status.',
      data:'Endpoint: /api/fleet-intel. Sursa: nave_master (activitate pe last_seen_buletin).'},
    {id:'flota',label:'Flotă Fluvială',access:'CEO, Commercial',
      desc:'Capacitate flotă fluvială: în port (barje/autopropulsate/tankuri), sosiri avizate, plecări avizate. Capacitate totală și leverage.',
      data:'Endpoint: /api/flota-capacity. Surse: fl_nfip, fl_af_sosire, fl_af_plecare, nave_master.'},
    {id:'heatmap',label:'Analiză Marfă',access:'CEO, Commercial',
      desc:'Heatmap operator × marfă, stacked bar marfă × proveniență și marfă × destinație. Analiza corelației între operatori, tipuri de marfă și rute.',
      data:'Endpoint-uri: /api/heatmap-operator-marfa, /api/marfa-prov, /api/marfa-dest. Surse: fl_nfip + mt_nso (deduplicated).'},
    {id:'users',label:'Utilizatori',access:'CEO, Admin',
      desc:'Gestiune utilizatori: creare, editare, activare/dezactivare, resetare parolă. Roluri disponibile: CEO, Commercial, Operations, Admin.',
      data:'Endpoint-uri: /api/users (CRUD). Sursa: tabel users. Parole stocate SHA256.'},
    {id:'settings',label:'Setări',access:'CEO, Admin',
      desc:'CRUD agenți portuari (cod → nume complet), operatori portuari, registru nave master.',
      data:'Endpoint-uri: /api/agent-codes, /api/operator-codes, /api/nave-master (CRUD). Surse: agenti_master, operatori_master, nave_master.'},
  ];

  return <div className="page-content">
    <div className="section-header">
      <h2>Help — Documentație Aplicație</h2>
      <p>Descrierea fiecărui meniu, sursa de date, și ce reprezintă informațiile afișate</p>
    </div>
    <div style={{display:'flex',flexDirection:'column',gap:12}}>
      {menus.map(m=><div key={m.id} className="card" style={{padding:16}}>
        <div style={{display:'flex',justifyContent:'space-between',alignItems:'center',marginBottom:8}}>
          <span style={{fontSize:15,fontWeight:700,color:'#e2e8f0'}}>{m.label}</span>
          <span className={'badge badge-blue'} style={{fontSize:10}}>{m.access}</span>
        </div>
        <p style={{fontSize:12,color:'#94a3b8',marginBottom:8,lineHeight:1.6}}>{m.desc}</p>
        <p style={{fontSize:11,color:'#64748b',lineHeight:1.5,fontFamily:'JetBrains Mono,monospace'}}>{m.data}</p>
      </div>)}
    </div>
    <div className="card" style={{padding:16,marginTop:16}}>
      <div style={{fontSize:14,fontWeight:700,color:'#e2e8f0',marginBottom:8}}>Baza de Date</div>
      <p style={{fontSize:12,color:'#94a3b8',lineHeight:1.6}}>Server: db01.tradingline.ro · Database: buletine_portuare · Engine: MariaDB</p>
      <p style={{fontSize:12,color:'#94a3b8',lineHeight:1.6}}>Tabele fluviale: fl_af_sosire (avizări sosire), fl_af_plecare (avizări plecare), fl_nfip (nave în port), fl_ril (remorchere/împingătoare)</p>
      <p style={{fontSize:12,color:'#94a3b8',lineHeight:1.6}}>Tabele maritime: mt_am (avizări maritime), mt_nso (sub operare), mt_nr (în radă), mt_nfop (fără operațiuni), mt_apo (în așteptare)</p>
      <p style={{fontSize:12,color:'#94a3b8',lineHeight:1.6}}>Tabele auxiliare: nave_master (26K+ nave), agenti_master, operatori_master, import_log, users</p>
      <p style={{fontSize:12,color:'#94a3b8',lineHeight:1.6}}>Parser: buletine_fluvial_v5_2.py (Pavle) · pdftotext -layout + position-aware extraction</p>
    </div>
  </div>;
}

const MENU = [
  {id:'dash',icon:IC.dash,label:'Dashboard',roles:['ceo','commercial','operations']},
  {id:'agency',icon:IC.db,label:'Port Agency',roles:['ceo','commercial','operations']},
  {id:'portmap',icon:IC.ops,label:'Hartă Port',roles:['ceo','commercial','operations']},
  {id:'comm',icon:IC.comm,label:'Commercial',roles:['ceo','commercial']},
  {id:'armatori',icon:IC.users,label:'Armatori',roles:['ceo','commercial']},
  {id:'convoaie',icon:IC.db,label:'Convoaie',roles:['ceo','commercial','operations']},
  {id:'ops',icon:IC.ops,label:'Operare',roles:['ceo','operations']},
  {id:'bunker',icon:IC.fuel,label:'Lichide',roles:['ceo','commercial','operations']},
  {id:'naveflu',icon:IC.ops,label:'Nave Fluv. Port',roles:['ceo','commercial','operations']},
  {id:'portpres',icon:IC.dash,label:'Prezență Port',roles:['ceo','commercial','operations']},
  {id:'fleet',icon:IC.db,label:'Fleet Intel',roles:['ceo','commercial']},
  {id:'flota',icon:IC.fuel,label:'Flotă Fluvială',roles:['ceo','commercial']},
  {id:'heatmap',icon:IC.gear,label:'Analiză Marfă',roles:['ceo','commercial']},
  {id:'_div'},
  {id:'users',icon:IC.users,label:'Utilizatori',roles:['ceo','admin'],group:'Config'},
  {id:'settings',icon:IC.gear,label:'Setări',roles:['ceo','admin'],group:'Config'},
  {id:'help',icon:IC.filt,label:'Help',roles:['ceo'],group:'Config'},
];

function App() {
  const [user,setUserState]=useState(getUser());
  const [page,setPage]=useState('dash');
  const [filters,setFilters]=useState({days:'30',mode:'day',date:'',start:'',end:'',port:''});
  const [collapsed,setCollapsed]=useState(false);
  const [snapshotDate,setSnapshotDate]=useState('');

  // Fetch latest bulletin date after login
  useEffect(()=>{
    if(!user) return;
    api('/snapshot').then(d=>{
      if(d?.snapshot_date) {
        const sd = String(d.snapshot_date).slice(0,10);
        setSnapshotDate(sd);
        setFilters(f=>({...f, date:f.date||sd}));
      }
    });
  },[user]);

  const login = u => { setUserState(u); };
  const logout = ()=>{ setToken(null); setUser(null); setUserState(null); };

  if(!user) return <LoginPage onLogin={login}/>;

  const ROLE_LABELS = {ceo:'CEO',commercial:'Commercial',operations:'Operare',admin:'Admin'};
  const vis = MENU.filter(m=>m.id==='_div'||m.roles?.includes(user.role));
  let lastGroup = null;

  return <div className="app">
    <div className={'sidebar'+(collapsed?' collapsed':'')}>
      <div className="sidebar-brand" onClick={()=>setCollapsed(!collapsed)}>
        <img src="/TL_logo.png" alt="TDL" className="brand-logo"/>
        {!collapsed&&<div className="brand-text"><div className="brand-name">Buletine</div><div className="brand-sub">Port Intelligence</div></div>}
      </div>
      <div className="sidebar-nav">
        {vis.map(m=>{
          if(m.id==='_div') return <div key={m.id} className="sidebar-divider"/>;
          let gh = null;
          if(m.group&&m.group!==lastGroup) { lastGroup=m.group; if(!collapsed) gh=<div className="sidebar-group">{m.group}</div>; }
          const act = page===m.id;
          return <div key={m.id}>{gh}<div className={'sidebar-item'+(act?' active':'')} onClick={()=>setPage(m.id)}>
            <Ico d={m.icon} s={18}/>{!collapsed&&<span>{m.label}</span>}
          </div></div>;
        })}
      </div>
      <div className="sidebar-user">
        <div className="avatar">{user.name.split(' ').map(n=>n[0]).join('')}</div>
        {!collapsed&&<div className="user-info"><div className="user-name">{user.name}</div><div className="user-role">{ROLE_LABELS[user.role]}</div></div>}
        {!collapsed&&<span className="logout-btn" onClick={logout}><Ico d={IC.out} s={16}/></span>}
      </div>
    </div>
    <div className="main">
      <Filters f={filters} set={setFilters} snapshotDate={snapshotDate}/>
      <div className="content">
        {page==='dash'&&<DashboardPage f={filters}/>}
        {page==='agency'&&<AgencyPage f={filters}/>}
        {page==='portmap'&&<PortMapPage/>}
        {page==='comm'&&<CommercialPage f={filters}/>}
        {page==='armatori'&&<ArmatoriPage f={filters}/>}
        {page==='convoaie'&&<ConvoaiePage f={filters}/>}
        {page==='ops'&&<OpsPage f={filters}/>}
        {page==='bunker'&&<BunkerPage f={filters}/>}
        {page==='naveflu'&&<NaveFluPage f={filters}/>}
        {page==='fleet'&&<FleetIntelPage f={filters}/>}
        {page==='flota'&&<FlotaPage f={filters}/>}
        {page==='heatmap'&&<HeatmapPage f={filters}/>}
        {page==='portpres'&&<PortPresencePage f={filters}/>}
        {page==='users'&&<UsersPage/>}
        {page==='settings'&&<SettingsPage/>}
        {page==='help'&&<HelpPage/>}
      </div>
    </div>
  </div>;
}

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