/* global React, Ic, useStore, AnimNumber, Sparkline */
const { useMemo: useDM, useState: useDS, useEffect: useDE } = React;

// Per-card date-range selector
function RangeSeg({ value, onChange }) {
  return (
    <div className="segmented">
      {[['today', 'วันนี้'], ['7d', '7 วัน'], ['30d', '30 วัน'], ['qtd', 'QTD']].map(([k, l]) => (
        <button key={k} className={value === k ? 'active' : ''} onClick={() => onChange(k)}>{l}</button>
      ))}
    </div>
  );
}

function PageDashboard({ onNav }) {
  const { state } = useStore();
  const [chartRange, setChartRange] = useDS('7d');
  const [topRange, setTopRange] = useDS('30d');
  const rangeDays = (r) => {
    if (r === 'today') return 1;
    if (r === '7d') return 7;
    if (r === '30d') return 30;
    // QTD — days since the start of the current quarter
    const n = new Date(); const qs = new Date(n.getFullYear(), Math.floor(n.getMonth() / 3) * 3, 1);
    return Math.max(1, Math.ceil((n - qs) / 86400000) + 1);
  };

  const kpis = useDM(() => {
    const totalQty = state.stock.reduce((a, b) => a + b.qty, 0);
    const totalValue = state.stock.reduce((a, b) => {
      const item = state.items.find(i => i.sku === b.sku);
      return a + b.qty * (item?.unit_cost || 0);
    }, 0);
    const totals = {};
    state.stock.forEach(s => { totals[s.sku] = (totals[s.sku] || 0) + s.qty; });
    const low = state.items.filter(i => (totals[i.sku] || 0) < i.min).length;
    const skuCount = state.items.length;
    // expiry
    const now = Date.now();
    const day30 = 30 * 86400000;
    const expiredQty = state.stock.filter(s => s.expiry && s.expiry < now).reduce((a,b)=>a+b.qty,0);
    const expiringQty = state.stock.filter(s => s.expiry && s.expiry >= now && s.expiry - now <= day30).reduce((a,b)=>a+b.qty,0);
    const expiringSku = new Set(state.stock.filter(s => s.expiry && s.expiry - now <= day30 && s.qty > 0).map(s => s.sku)).size;
    // shelf-life alert lots — same threshold as the "เตือนอายุสินค้า" panel (< 1.5y remaining)
    const lifeAlertLots = state.stock.filter(s => s.expiry && s.qty > 0 && Math.floor((s.expiry - now) / 86400000) < 548).length;
    return { totalQty, totalValue, low, skuCount, expiredQty, expiringQty, expiringSku, lifeAlertLots };
  }, [state]);

  // Expiring stock entries — for the alerts strip
  const expiringList = useDM(() => {
    const now = Date.now();
    return state.stock
      .filter(s => s.expiry && s.qty > 0)
      .map(s => ({
        ...s,
        item: state.items.find(i => i.sku === s.sku),
        location: state.locations.find(l => l.id === s.locId),
        days: Math.floor((s.expiry - now) / 86400000),
      }))
      .filter(s => s.days <= 90)
      .sort((a,b) => a.days - b.days)
      .slice(0, 6);
  }, [state]);

  // Inbound/Outbound daily series for the selected range
  const series = useDM(() => {
    const days = rangeDays(chartRange);
    const today = new Date(); today.setHours(0, 0, 0, 0);
    const inSeries = Array(days).fill(0);
    const outSeries = Array(days).fill(0);
    state.movements.forEach(m => {
      const d = new Date(m.ts); d.setHours(0,0,0,0);
      const diff = Math.floor((today - d) / 86400000);
      if (diff >= 0 && diff < days) {
        if (m.type === 'IN') inSeries[days - 1 - diff] += m.qty;
        if (m.type === 'OUT') outSeries[days - 1 - diff] += m.qty;
      }
    });
    return { inSeries, outSeries };
  }, [state.movements, chartRange]);

  // Per-warehouse Location utilization = locations holding stock / total locations
  const whStats = useDM(() => {
    const usedLocIds = new Set(state.stock.filter(s => s.qty > 0).map(s => s.locId));
    return state.warehouses.map(wh => {
      const locs = state.locations.filter(l => l.wh === wh.id);
      const total = locs.length;
      const used = locs.filter(l => usedLocIds.has(l.id)).length;
      return { id: wh.id, name: wh.name, used, total, pct: total ? Math.round(used / total * 100) : 0 };
    });
  }, [state]);

  const recent = state.movements.slice(0, 7);
  // Shelf-life alerts: any lot whose remaining life is under 1.5 years, colour-tiered
  const lifeAlerts = useDM(() => {
    const now = Date.now();
    const tierOf = (days) =>
      days < 183 ? { key: 'red',    c: '#dc2626', label: '< 6 เดือน' } :
      days < 365 ? { key: 'orange', c: '#ea580c', label: '< 1 ปี' } :
      days < 548 ? { key: 'yellow', c: '#b45309', label: '< 1.5 ปี' } : null;
    return state.stock
      .filter(s => s.expiry && s.qty > 0)
      .map(s => ({ ...s, item: state.items.find(i => i.sku === s.sku), days: Math.floor((s.expiry - now) / 86400000) }))
      .map(s => ({ ...s, t: tierOf(s.days) }))
      .filter(s => s.t)
      .sort((a, b) => a.days - b.days);
  }, [state]);

  const topMoving = useDM(() => {
    const cutoff = Date.now() - rangeDays(topRange) * 86400000;
    const counts = {};
    state.movements.filter(m => m.ts >= cutoff).forEach(m => {
      counts[m.sku] = (counts[m.sku] || 0) + m.qty;
    });
    return Object.entries(counts)
      .sort((a,b)=>b[1]-a[1])
      .slice(0,5)
      .map(([sku, q]) => ({ sku, qty: q, item: state.items.find(i => i.sku === sku) }));
  }, [state.movements, topRange]);

  return (
    <div className="page-enter">
      <div className="page-header">
        <div>
          <h2 className="page-title">Operations Dashboard</h2>
          <div className="page-subtitle">// LIVE_OVERVIEW · {new Date().toLocaleDateString('th-TH', {dateStyle:'full'})}</div>
        </div>
        <div className="row">
          <button className="btn btn-ghost"><Ic name="export" size={14}/>Export</button>
          <button className="btn btn-primary" onClick={() => onNav('receive')}><Ic name="plus" size={14}/>เริ่มรับเข้า</button>
        </div>
      </div>

      {/* KPIs */}
      <div className="kpi-grid">
        <KPI label="Total Inventory" value={kpis.totalQty} suffix=" units" delta="+4.8%" up sparkData={[3,5,4,6,7,6,9,8,10,9,11]} color="var(--accent)"/>
        <KPI label="Inventory Value" value={kpis.totalValue} prefix="฿" delta="+12%" up sparkData={[2,4,3,5,6,5,7,6,8,9,11]} color="var(--info)"/>
        <KPI label="Low Stock" value={kpis.low} suffix=" SKUs" delta="-3" warn sparkData={[7,8,9,8,7,7,6,5,5,4,4]} color="var(--warning)"/>
        <KPI label="Expiry Alerts" value={kpis.lifeAlertLots} suffix=" ล็อต" delta={kpis.expiredQty > 0 ? `${kpis.expiredQty.toLocaleString()}u expired` : kpis.lifeAlertLots > 0 ? 'เฝ้าระวัง' : 'OK'} warn={kpis.lifeAlertLots > 0} sparkData={[1,2,2,3,4,5,4,6,5,7,8]} color="var(--danger)"/>
      </div>

      {/* Expiring stock strip */}
      {expiringList.length > 0 && (
        <div className="card tech expiry-strip" style={{ marginBottom: 14 }}>
          <div className="card-head">
            <div>
              <div className="card-title">
                <Ic name="alert" size={14} style={{ display: 'inline', marginRight: 6, color: 'var(--danger)' }}/>
                อายุสินค้าใกล้หมด / หมดอายุแล้ว
              </div>
              <div className="card-sub">EXPIRY_WATCH · NEXT_90_DAYS</div>
            </div>
            <div className="row" style={{ gap: 8 }}>
              <span className="badge crit">⚠ หมดอายุ {kpis.expiredQty.toLocaleString()} units</span>
              <span className="badge warn">⏱ ใกล้หมด {kpis.expiringQty.toLocaleString()} units</span>
              <button className="btn btn-ghost btn-sm" onClick={() => onNav('stock-report')}>ดูรายงาน →</button>
            </div>
          </div>
          <div className="expiry-row">
            {expiringList.map(e => {
              const st = expiryStatus(e.expiry);
              return (
                <div key={e.locId + e.lot} className={`expiry-card ${st.cls}`}>
                  <div className="row" style={{ justifyContent: 'space-between', marginBottom: 6 }}>
                    <span className="mono" style={{ fontSize: 10, color: 'var(--text-muted)' }}>{e.sku}</span>
                    <span className={`badge ${st.badge}`}>{st.label}</span>
                  </div>
                  <div style={{ fontSize: 12.5, fontWeight: 600, lineHeight: 1.25, marginBottom: 6, color: 'var(--text-primary)', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
                    {e.item?.name_th || e.sku}
                  </div>
                  <div className="mono" style={{ fontSize: 10, color: 'var(--text-muted)' }}>
                    📍 {e.locId}
                  </div>
                  <div className="row" style={{ justifyContent: 'space-between', marginTop: 6, paddingTop: 6, borderTop: '1px dashed var(--border)' }}>
                    <span className="mono" style={{ fontSize: 10, color: 'var(--text-muted)' }}>EXP {fmtDate(e.expiry)}</span>
                    <span className="mono" style={{ fontSize: 11.5, color: 'var(--accent)', fontWeight: 600 }}>{e.qty} u</span>
                  </div>
                </div>
              );
            })}
          </div>
        </div>
      )}

      {/* Chart + Zones */}
      <div className="grid-2" style={{ gridTemplateColumns: '1.6fr 1fr', marginBottom: 14 }}>
        <div className="card tech">
          <div className="card-head">
            <div>
              <div className="card-title">Inbound vs Outbound</div>
              <div className="card-sub">QTY_MOVED · UNITS</div>
            </div>
            <div className="row" style={{ gap: 12, flexWrap: 'wrap' }}>
              <span className="lead-dot" style={{ color: 'var(--accent)'}}>รับเข้า</span>
              <span className="lead-dot" style={{ color: 'var(--warning)'}}>จ่ายออก</span>
              <RangeSeg value={chartRange} onChange={setChartRange}/>
            </div>
          </div>
          <BigChart inSeries={series.inSeries} outSeries={series.outSeries}/>
        </div>

        <div className="card tech">
          <div className="card-head">
            <div>
              <div className="card-title">ภาพรวมแต่ละ Warehouse</div>
              <div className="card-sub">LOCATION ที่ใช้ / ทั้งหมด</div>
            </div>
            <button className="btn btn-ghost btn-sm" onClick={() => onNav('locations')}>ดูแผนผัง<Ic name="arrow-right" size={12}/></button>
          </div>
          <div style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>
            {whStats.map(w => (
              <div key={w.id}>
                <div className="row" style={{ justifyContent: 'space-between', marginBottom: 4 }}>
                  <div className="row" style={{ gap: 8, minWidth: 0 }}>
                    <span className="mono" style={{ fontSize: 11, color: 'var(--accent)' }}>{w.id}</span>
                    <span style={{ fontSize: 12, color: 'var(--text-secondary)', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{w.name}</span>
                  </div>
                  <span className="mono" style={{ fontSize: 11, color: 'var(--text-muted)', flexShrink: 0 }}>
                    <span style={{ color: 'var(--text-primary)', fontWeight: 600 }}>{w.used}</span> / {w.total} Loc
                    <span style={{ color: 'var(--accent)', marginLeft: 6 }}>({w.pct}%)</span>
                  </span>
                </div>
                <div style={{ height: 6, background: 'var(--bg-card-2)', borderRadius: 4, overflow: 'hidden' }}>
                  <div style={{
                    width: `${w.pct}%`, height: '100%',
                    background: w.pct > 85 ? 'linear-gradient(90deg, var(--warning), var(--danger))' :
                                w.pct > 60 ? 'linear-gradient(90deg, var(--accent), var(--info))' :
                                              'linear-gradient(90deg, var(--success), var(--accent))',
                    transition: 'width 1s cubic-bezier(0.2,0.7,0.2,1)'
                  }}/>
                </div>
              </div>
            ))}
            {whStats.length === 0 && <div className="mono" style={{ fontSize: 12, color: 'var(--text-muted)', textAlign: 'center', padding: 16 }}>ยังไม่มีคลัง</div>}
          </div>
        </div>
      </div>

      {/* Low stock + Top moving + Recent activity */}
      <div className="grid-2" style={{ gridTemplateColumns: '1fr 1fr 1.2fr', display: 'grid', gridTemplateColumns: '1fr 1fr 1.2fr', gap: 14 }}>
        <div className="card tech">
          <div className="card-head">
            <div>
              <div className="card-title">เตือนอายุสินค้า</div>
              <div className="card-sub">SHELF_LIFE · เหลือ &lt; 1.5 ปี</div>
            </div>
            <span className="badge crit">{lifeAlerts.length} ล็อต</span>
          </div>
          {lifeAlerts.length === 0 ? (
            <div className="empty"><Ic name="check-circle" size={28}/>ไม่มีล็อตใกล้หมดอายุ</div>
          ) : (
            <div style={{ display: 'flex', flexDirection: 'column', gap: 8, maxHeight: 340, overflowY: 'auto', paddingRight: 4 }}>
              {lifeAlerts.map(a => (
                <div key={a.locId + a.lot} className="row" style={{ gap: 10, alignItems: 'center', borderLeft: `3px solid ${a.t.c}`, paddingLeft: 9 }}>
                  <div style={{ flex: 1, minWidth: 0 }}>
                    <div style={{ fontSize: 12.5, color: 'var(--text-primary)', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{a.item?.name_th || a.sku}</div>
                    <div className="mono" style={{ fontSize: 10, color: 'var(--text-muted)' }}>{a.locId} · {a.qty.toLocaleString()} u · LOT {a.lot}</div>
                  </div>
                  <div style={{ textAlign: 'right', flexShrink: 0 }}>
                    <div className="mono" style={{ fontSize: 12, fontWeight: 700, color: a.t.c }}>เหลือ {a.days.toLocaleString()} วัน</div>
                    <div className="mono" style={{ fontSize: 9, color: 'var(--text-muted)' }}>{a.t.label} · EXP {fmtDate(a.expiry)}</div>
                  </div>
                </div>
              ))}
            </div>
          )}
        </div>

        <div className="card tech">
          <div className="card-head">
            <div>
              <div className="card-title">Top Moving SKUs</div>
              <div className="card-sub">QTY_MOVED · BY_RANGE</div>
            </div>
            <RangeSeg value={topRange} onChange={setTopRange}/>
          </div>
          <div style={{ display: 'flex', flexDirection: 'column', gap: 10 }}>
            {topMoving.map((m, idx) => {
              const max = topMoving[0].qty;
              return (
                <div key={m.sku}>
                  <div className="row" style={{ justifyContent: 'space-between', marginBottom: 4 }}>
                    <div className="row" style={{ gap: 8 }}>
                      <span className="mono" style={{ fontSize: 10, color: 'var(--text-muted)', minWidth: 14 }}>#{idx + 1}</span>
                      <span style={{ fontSize: 12.5 }}>{m.item?.name_th || m.sku}</span>
                    </div>
                    <span className="mono" style={{ fontSize: 11.5, color: 'var(--accent)' }}>{m.qty.toLocaleString()} u</span>
                  </div>
                  <div style={{ height: 4, background: 'var(--bg-card-2)', borderRadius: 4, overflow: 'hidden' }}>
                    <div style={{
                      width: `${(m.qty / max) * 100}%`, height: '100%',
                      background: 'linear-gradient(90deg, var(--accent), var(--info))',
                      transition: 'width 1s cubic-bezier(0.2,0.7,0.2,1)',
                      animation: 'barRise 0.7s ease-out',
                    }}/>
                  </div>
                </div>
              );
            })}
          </div>
        </div>

        <div className="card tech">
          <div className="card-head">
            <div>
              <div className="card-title">Recent Activity</div>
              <div className="card-sub">REAL_TIME · MOVEMENT_LOG</div>
            </div>
            <button className="btn btn-ghost btn-sm" onClick={() => onNav('movement')}>ดูทั้งหมด</button>
          </div>
          <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
            {recent.map(m => <ActivityRow key={m.id} m={m}/>)}
          </div>
        </div>
      </div>
    </div>
  );
}

function KPI({ label, value, prefix, suffix, delta, up, warn, sparkData, color }) {
  return (
    <div className="card kpi tech">
      <div className="kpi-label">
        {label}
        {delta && <span className={`kpi-delta ${up ? 'up' : 'down'}`}>{up ? '▲' : '▼'} {delta}</span>}
      </div>
      <div className="kpi-value">
        <AnimNumber value={value} prefix={prefix} suffix={suffix}/>
      </div>
      <div className="kpi-trend">
        <Sparkline data={sparkData} color={color}/>
      </div>
    </div>
  );
}

function BigChart({ inSeries, outSeries }) {
  const w = 700, h = 220, pad = 32;
  const max = Math.max(...inSeries, ...outSeries, 10);
  const pts = (arr) => arr.map((v, i) => {
    const x = pad + (i / (arr.length - 1)) * (w - pad * 2);
    const y = h - pad - (v / max) * (h - pad * 2);
    return [x, y];
  });
  const pIn = pts(inSeries);
  const pOut = pts(outSeries);
  const path = (pp) => pp.map((p, i) => (i === 0 ? `M${p[0]},${p[1]}` : `L${p[0]},${p[1]}`)).join(' ');
  const area = (pp) => path(pp) + ` L${pp[pp.length-1][0]},${h-pad} L${pp[0][0]},${h-pad} Z`;
  return (
    <svg viewBox={`0 0 ${w} ${h}`} style={{ width: '100%', height: 240 }}>
      <defs>
        <linearGradient id="inGrad" x1="0" y1="0" x2="0" y2="1">
          <stop offset="0%" stopColor="#2563eb" stopOpacity="0.28"/>
          <stop offset="100%" stopColor="#2563eb" stopOpacity="0"/>
        </linearGradient>
        <linearGradient id="warnGrad" x1="0" y1="0" x2="0" y2="1">
          <stop offset="0%" stopColor="#f5b32a" stopOpacity="0.22"/>
          <stop offset="100%" stopColor="#f5b32a" stopOpacity="0"/>
        </linearGradient>
      </defs>
      {/* grid */}
      {[0.25, 0.5, 0.75].map((p, i) => (
        <line key={i} x1={pad} x2={w-pad} y1={pad + (h-pad*2)*p} y2={pad + (h-pad*2)*p} stroke="var(--border)" strokeDasharray="2 4"/>
      ))}
      {/* x labels */}
      {inSeries.map((_, i) => {
        if (i % 2 !== 0 || i === inSeries.length - 1) return null;
        const x = pad + (i / (inSeries.length - 1)) * (w - pad * 2);
        const d = new Date(); d.setDate(d.getDate() - (inSeries.length - 1 - i));
        return <text key={i} x={x} y={h - 10} textAnchor="middle" className="chart-axis">{d.getDate()}/{d.getMonth()+1}</text>;
      })}
      {[0, 0.5, 1].map((p, i) => (
        <text key={i} x={pad - 6} y={h - pad - (h-pad*2) * p + 4} textAnchor="end" className="chart-axis">{Math.round(max * p)}</text>
      ))}
      {/* outbound first, inbound drawn on top so it's always visible.
          No opacity/animation gating — lines stay visible even with reduced-motion. */}
      <path d={area(pOut)} fill="url(#warnGrad)"/>
      <path d={area(pIn)} fill="url(#inGrad)"/>
      <path d={path(pOut)} fill="none" stroke="#f5b32a" strokeWidth="2.5" strokeLinejoin="round" strokeLinecap="round"/>
      <path d={path(pIn)} fill="none" stroke="var(--accent)" strokeWidth="2.5" strokeLinejoin="round" strokeLinecap="round"/>
      {pOut.map((p, i) => <circle key={`o${i}`} cx={p[0]} cy={p[1]} r="2.6" fill="#f5b32a"/>)}
      {pIn.map((p, i) => <circle key={`a${i}`} cx={p[0]} cy={p[1]} r="2.6" fill="var(--accent)"/>)}
    </svg>
  );
}

function ActivityRow({ m }) {
  const type = m.type;
  const map = {
    IN: { ic: 'arrow-down', cls: 'ok', label: 'รับเข้า' },
    OUT: { ic: 'arrow-up', cls: 'warn', label: 'จ่ายออก' },
    TRANSFER: { ic: 'transfer', cls: 'info', label: 'โอน' },
    COUNT: { ic: 'count', cls: 'purple', label: 'ตรวจนับ' },
  };
  const meta = map[type] || map.IN;
  const tDiff = (Date.now() - m.ts) / 60000;
  const when = tDiff < 60 ? `${Math.max(1, Math.floor(tDiff))}m ago` : tDiff < 1440 ? `${Math.floor(tDiff/60)}h ago` : `${Math.floor(tDiff/1440)}d ago`;
  return (
    <div className="row" style={{ padding: '6px 0', borderBottom: '1px dashed var(--border)', gap: 10 }}>
      <span className={`badge ${meta.cls}`}><Ic name={meta.ic} size={11}/>{meta.label}</span>
      <span className="mono" style={{ fontSize: 11, color: 'var(--text-secondary)' }}>{m.sku}</span>
      <span className="mono" style={{ fontSize: 11, color: 'var(--accent)' }}>×{m.qty}</span>
      <span className="spacer"/>
      <span className="mono" style={{ fontSize: 10.5, color: 'var(--text-muted)' }}>{when}</span>
    </div>
  );
}

window.PageDashboard = PageDashboard;
