/* screens-customer-detail.jsx — Customer detail page shell + Kế hoạch tab.
   Reuses widgets from forecast overview (KPI tiles, DualAxisChart, LineChart,
   Daily detail table) — plus customer-specific approvals + alerts. */

// ============================================================
// Detail page (shell)
// ============================================================
function CustomerDetailPage({ customerId, onBack, navigate }) {
  const [tab, setTab] = React.useState('plan');
  const c = WFP.CUSTOMERS_EXT.find(x => x.id === customerId);
  const { isMobile } = useViewport();
  if (!c) {
    return <Empty icon="users" title="Không tìm thấy khách hàng"
      action={<Button variant="primary" onClick={onBack}>Quay lại danh sách</Button>}/>;
  }

  const pendingCount = WFP.OVERRIDE_REQUESTS.filter(r => r.customerId === c.id && r.status === 'PENDING').length;
  const alertCount = computeAlerts(c).filter(a => a.severity !== 'INFO').length;

  return (
    <div style={{ display: 'flex', flexDirection: 'column', height: '100%' }}>
      <PageHeader
        breadcrumb={['Dự báo', 'Khách hàng', c.name]}
        title={
          <span style={{ display: 'inline-flex', alignItems: 'center', gap: 12, lineHeight: 1.2 }}>
            <IconBtn name="chevron-left" onClick={onBack} title="Quay lại" size={32}
              style={{ background: 'var(--bx-surface-2)', border: '1px solid var(--bx-border-muted)' }}/>
            <Avatar name={c.name} size={32}/>
            <span>{c.name}</span>
            <Badge kind={c.tier === 'KEY' ? 'APPROVED' : c.tier === 'MAJOR' ? 'INFO' : 'INACTIVE'} size="sm">{c.tier}</Badge>
          </span>
        }
        subtitle={c.segment + ' · ' + c.code + ' · KAM ' + c.submittedBy.split('@')[0]
          + ' · Kho chính ' + (WFP.WAREHOUSES.find(w => w.id === c.warehouses)?.code || '—')}
        actions={
          <>
            <Button variant="outline" icon="mail">Ping KAM</Button>
            {pendingCount > 0 && (
              <Button variant="outline" icon="check" onClick={() => navigate('/planner/forecast/review')}>
                {isMobile ? pendingCount + ' chờ' : pendingCount + ' yêu cầu chờ duyệt'}
              </Button>
            )}
            <Button variant="primary" icon="upload" onClick={() => navigate('/planner/override-import')}>
              {isMobile ? 'Gửi' : 'Gửi điều chỉnh'}
            </Button>
          </>
        }>
        <div style={{ marginTop: 4 }}>
          <SectionTabs value={tab} onChange={setTab} tabs={[
            { id: 'plan',   idx: '1', label: 'Kế hoạch' },
            { id: 'config', idx: '2', label: 'Tùy chỉnh' },
          ]}/>
        </div>
      </PageHeader>
      {tab === 'plan'   ? <CustomerPlanTab   c={c} navigate={navigate}/> : null}
      {tab === 'config' ? <CustomerConfigTab c={c}/> : null}
    </div>
  );
}

// ============================================================
// Plan tab
// ============================================================
function CustomerPlanTab({ c, navigate }) {
  const [range, setRange] = React.useState('14d');       // '7d' | '14d' | '30d'
  const [metric, setMetric] = React.useState('qty');     // 'qty' or 'wlu'
  const [whScope, setWhScope] = React.useState('all');   // 'all' or wh-id
  const [dayTypeFilter, setDayTypeFilter] = React.useState('all'); // 'all' | 'MEGA_SALE' | ...
  const { isMobile, vw } = useViewport();

  const TODAY = new Date('2026-05-18T00:00:00Z');
  const days = range === '7d' ? 7 : range === '14d' ? 14 : 30;
  // Center window on today (half past, half future)
  const past = Math.floor(days * 0.5);
  const future = days - past;

  // Build per-day series from c.series + c.forecast, filtered by warehouse share (proxy)
  const whShare = whScope === 'all' ? 1 : (c.warehouses === whScope ? 0.82 : 0.18);
  const series = buildCustomerSeries(c, TODAY, whShare);
  const sliced = series.filter(r => {
    const off = Math.round((new Date(r.date) - TODAY) / 86400000);
    if (off < -past || off >= future) return false;
    if (dayTypeFilter !== 'all' && r.dayType !== dayTypeFilter) return false;
    return true;
  });

  // KPIs
  function rangeSum(rows, off0, off1, key) {
    return rows.reduce((s, r) => {
      const off = Math.round((new Date(r.date) - TODAY) / 86400000);
      return (off >= off0 && off <= off1) ? s + (r[key] || 0) : s;
    }, 0);
  }
  const last7   = rangeSum(series, -7, -1, metric);
  const prev7   = rangeSum(series, -14, -8, metric);
  const next14  = rangeSum(series, 0, 13, metric);
  const last7Cap  = rangeSum(series, -7, -1, 'capacity') || 1;
  const next14Cap = rangeSum(series, 0, 13, 'capacity') || 1;
  const next14WoW = ((next14 - last7) / (last7 || 1)) * 100;
  const last7WoW  = ((last7 - prev7) / (prev7 || 1)) * 100;
  const utilNext  = (next14 / next14Cap) * 100;

  const approvals = WFP.OVERRIDE_REQUESTS.filter(r => r.customerId === c.id);
  const alerts = computeAlerts(c);

  // Warehouses where this customer ships (top 3 shown)
  const customerWhs = ['wh-vn-hn-01', 'wh-vn-hcm-01', 'wh-vn-hcm-02'].slice(0, 2 + (c.tier === 'KEY' ? 1 : 0));

  return (
    <div style={{ flex: 1, overflowY: 'auto', padding: isMobile ? 14 : 20, display: 'flex', flexDirection: 'column', gap: 16 }}>
      {/* Filter row — mirrors forecast overview */}
      <Card padding={0}>
        <div style={{ padding: '12px 14px', display: 'flex', alignItems: 'center', gap: 10, flexWrap: 'wrap' }}>
          <div style={{ fontSize: 11, color: 'var(--bx-text-muted)', textTransform: 'uppercase', letterSpacing: '0.06em', fontWeight: 700 }}>Kho</div>
          <Tabs value={whScope} onChange={setWhScope} dense tabs={[
            { id: 'all', label: 'Tất cả' },
            ...customerWhs.map(id => ({ id, label: WFP.WAREHOUSES.find(w => w.id === id)?.code || id })),
          ]}/>
          <div style={{ width: 1, height: 22, background: 'var(--bx-border-muted)' }}/>
          <div style={{ width: 150 }}>
            <Select size="sm" value={dayTypeFilter} onChange={e => setDayTypeFilter(e.target.value)} options={[
              { value: 'all',        label: 'Tất cả loại ngày' },
              { value: 'NORMAL',     label: 'Bình thường' },
              { value: 'PAYDAY',     label: 'Ngày lương' },
              { value: 'MINI_SPIKE', label: 'Sale nhỏ' },
              { value: 'MEGA_SALE',  label: 'Sale lớn' },
              { value: 'SUNDAY',     label: 'Chủ nhật' },
            ]}/>
          </div>
          <div style={{ flex: 1 }}/>
          <Tabs value={range} onChange={setRange} dense tabs={[
            { id: '7d',  label: '7 ngày' },
            { id: '14d', label: '14 ngày' },
            { id: '30d', label: '30 ngày' },
          ]}/>
          <div style={{ width: 1, height: 22, background: 'var(--bx-border-muted)' }}/>
          <Tabs value={metric} onChange={setMetric} dense tabs={[
            { id: 'qty', label: 'Sản lượng', icon: 'cube' },
            { id: 'wlu', label: 'WLU',       icon: 'spark' },
          ]}/>
        </div>
      </Card>

      {/* KPI row */}
      <div style={{
        display: 'grid', gap: 12,
        gridTemplateColumns: vw < 560 ? 'repeat(2, 1fr)' : 'repeat(4, 1fr)',
      }}>
        <Metric icon="history" label={'7 ngày qua · ' + (metric === 'qty' ? 'sản lượng' : 'WLU')}
          value={fmt.int(last7)}
          sublabel={'WoW ' + (last7WoW > 0 ? '+' : '') + last7WoW.toFixed(1) + '%'}
          deltaTone={last7WoW >= 0 ? 'up' : 'down'} delta={fmt.signed(Math.round(last7 - prev7))}/>
        <Metric icon="forecast" label="14 ngày tới · dự báo"
          value={fmt.int(next14)}
          sublabel={'vs 7d qua ' + (next14WoW > 0 ? '+' : '') + next14WoW.toFixed(0) + '%'}
          deltaTone={next14WoW >= 0 ? 'up' : 'down'} delta={fmt.signed(Math.round(next14 - last7))}/>
        <Metric icon="plan" label="Tỷ lệ dùng năng lực"
          value={utilNext.toFixed(0) + '%'}
          sublabel={'trần ' + fmt.int(next14Cap) + ' / 14d'}
          deltaTone={utilNext > 90 ? 'down' : utilNext > 75 ? 'flat' : 'up'}
          delta={utilNext > 90 ? 'vượt 90%' : utilNext > 75 ? 'sát ngưỡng' : 'ổn'}/>
        <Metric icon="warning" label="Ngày cao điểm · 14d tới"
          value={(function () {
            const peak = series.filter(r => r.isFuture).reduce((m, r) => r.qty > m.qty ? r : m, { qty: 0, date: '—', dayType: '—' });
            return peak.date === '—' ? '—' : fmt.shortDate(peak.date);
          })()}
          sublabel={(function () {
            const peak = series.filter(r => r.isFuture).reduce((m, r) => r.qty > m.qty ? r : m, { qty: 0, date: '—', dayType: '—' });
            return viLabel(peak.dayType) + ' · ' + fmt.int(peak.qty) + ' đơn';
          })()}/>
      </div>

      {/* Daily orders chart */}
      <Card title="Sản lượng theo ngày" subtitle={range + ' xoay quanh hôm nay · ' + (metric === 'qty' ? 'đơn vị' : 'WLU')}>
        <ChartLegend items={[
          { color: '#0b43ea', label: metric === 'qty' ? 'Sản lượng (dự báo / thực tế)' : 'WLU dự báo' },
          { color: '#ff6467', label: 'Baseline forecast (trước override)', dashed: true },
          { color: '#99a1af', label: 'Trần năng lực', dashed: true },
        ]} style={{ marginBottom: 10 }}/>
        <LineChart
          data={sliced}
          height={260}
          xKey="label"
          lines={[
            { key: 'baselineQty', label: 'Baseline',          color: '#ff6467', width: 1.5, dashed: true },
            { key: 'capacity',    label: 'Trần năng lực',     color: '#99a1af', width: 1,   dashed: true },
            { key: metric,        label: metric === 'qty' ? 'Sản lượng' : 'WLU', color: '#0b43ea', width: 2.5 },
          ]}
        />
        <div style={{ display: 'flex', gap: 14, marginTop: 8, fontSize: 11, color: 'var(--bx-text-muted)', flexWrap: 'wrap' }}>
          <span><Icon name="info" size={10}/> Ngày trước hôm nay là thực tế; ngày sau là dự báo (có override nếu KAM đã gửi).</span>
        </div>
      </Card>

      {/* Volume vs workload dual-axis */}
      <Card title="Sản lượng vs WLU" subtitle="Độ phức tạp đẩy WLU cao hơn sản lượng vào ngày sale lớn — cảnh báo sớm áp lực nhân sự.">
        <ChartLegend items={[
          { color: '#0b43ea', label: 'Sản lượng (đơn)' },
          { color: '#ff6467', label: 'WLU (workload unit)' },
          { color: '#ff6467', label: 'Sale lớn' },
        ]} style={{ marginBottom: 8 }}/>
        <DualAxisChart data={sliced} height={260}
          barKey="qty" lineKey="wlu"
          barLabel="Sản lượng" lineLabel="WLU"
          xKey="label"/>
      </Card>

      {/* Approvals + Alerts (side by side) */}
      <div style={{ display: 'grid', gridTemplateColumns: vw < 1100 ? '1fr' : '1.6fr 1fr', gap: 16 }}>
        <ApprovalsCard rows={approvals} navigate={navigate}/>
        <AlertsCard alerts={alerts}/>
      </div>

      {/* Daily detail table */}
      <Card title="Chi tiết theo ngày" subtitle="Sản lượng + WLU + so sánh với cùng kỳ sale trước"
        padding={0}
        actions={!isMobile && <Button variant="ghost" size="sm" icon="excel">Xuất Excel</Button>}>
        <Table dense stickyHeader
          columns={[
            { header: 'Ngày', mono: true, render: r => (
              <div>
                <div style={{ fontWeight: 600, color: 'var(--bx-text-dark)' }}>{fmt.shortDate(r.date)}</div>
                <div style={{ fontSize: 10.5, color: 'var(--bx-text-muted)' }}>
                  {viWeekday(r.date)}{r.isFuture ? ' · dự báo' : ' · thực tế'}
                </div>
              </div>
            )},
            { header: 'Loại ngày', priority: 2, render: r => (
              <Badge kind={
                r.dayType === 'MEGA_SALE' ? 'CRITICAL'
                : r.dayType === 'MINI_SPIKE' ? 'WARNING'
                : r.dayType === 'PAYDAY' ? 'INFO'
                : 'INACTIVE'
              } size="sm">{viLabel(r.dayType)}</Badge>
            )},
            { header: 'Sản lượng', mono: true, align: 'right', render: r => fmt.int(r.qty) },
            { header: 'WLU',       mono: true, align: 'right', render: r => fmt.int(r.wlu) },
            { header: 'Baseline',  priority: 2, mono: true, align: 'right', render: r => r.baselineQty ? fmt.int(r.baselineQty) : <span style={{ color: 'var(--bx-text-muted)' }}>—</span> },
            { header: 'Δ vs cùng kỳ', priority: 2, render: r => {
              if (!r.lastSaleQty) return <span style={{ color: 'var(--bx-text-muted)' }}>—</span>;
              const d = r.qty - r.lastSaleQty;
              const pct = (d / r.lastSaleQty) * 100;
              return <span style={{ fontFamily: 'var(--bx-font-mono)', fontVariantNumeric: 'tabular-nums', fontWeight: 600,
                color: d > 0 ? 'var(--bx-success)' : d < 0 ? 'var(--bx-error)' : 'var(--bx-text-muted)' }}>
                {d > 0 ? '+' : ''}{pct.toFixed(0)}%
              </span>;
            }},
            { header: 'Tỷ lệ năng lực', priority: 2, render: r => {
              const u = (r.wlu / r.capacity) * 100;
              return (
                <div style={{ display: 'flex', alignItems: 'center', gap: 8, minWidth: 120 }}>
                  <div style={{ flex: 1, height: 6, background: 'var(--bx-surface-2)', borderRadius: 6, overflow: 'hidden' }}>
                    <div style={{ height: '100%', width: Math.min(100, u) + '%',
                      background: u > 95 ? 'var(--bx-error)' : u > 80 ? 'var(--bx-warning)' : 'var(--bx-primary)' }}/>
                  </div>
                  <span style={{ fontFamily: 'var(--bx-font-mono)', fontVariantNumeric: 'tabular-nums', fontSize: 11.5, color: 'var(--bx-text-muted)' }}>{u.toFixed(0)}%</span>
                </div>
              );
            }},
          ]}
          rows={sliced} getRowKey={r => r.date}/>
      </Card>
    </div>
  );
}

// ============================================================
// Helpers
// ============================================================
function buildCustomerSeries(c, TODAY, whShare) {
  // Combine 30d history + 14d forecast into a unified series for charts
  const out = [];
  const cap = Math.max(c.avgDaily * 2.6, 600);
  for (let i = -30; i < 0; i++) {
    const date = new Date(TODAY.getTime() + i * 86400000).toISOString().slice(0, 10);
    const qty = Math.round((c.series[i + 30] || 0) * whShare);
    const wlu = Math.round((c.wluSeries[i + 30] || 0) * whShare);
    const dayType = WFP.dayTypeOf(date);
    out.push({
      date, label: date.slice(5),
      qty, wlu,
      baselineQty: Math.round(qty * 0.95),
      capacity: Math.round(cap * whShare),
      dayType, isFuture: false,
      lastSaleQty: Math.round(qty * (0.86 + ((i * 7) % 21) / 100)),
    });
  }
  c.forecast.forEach((f, i) => {
    const sub = (f.submittedQty || f.forecastQty);
    const qty = Math.round(sub * whShare);
    const wlu = Math.round(qty * (f.dayType === 'MEGA_SALE' ? 1.32 : f.dayType === 'MINI_SPIKE' ? 1.18 : 1.0));
    out.push({
      date: f.date, label: f.date.slice(5),
      qty, wlu,
      baselineQty: Math.round(f.forecastQty * whShare),
      capacity: Math.round(cap * whShare),
      dayType: f.dayType, isFuture: true,
      submittedQty: f.submittedQty != null ? Math.round(f.submittedQty * whShare) : null,
      lastSaleQty: Math.round(qty * (0.86 + ((i * 11) % 19) / 100)),
    });
  });
  return out;
}

function computeAlerts(c) {
  const out = [];
  // Overdue submit
  if (c.submitStatus === 'OVERDUE') {
    out.push({
      severity: 'CRITICAL', icon: 'warning',
      title: 'KAM chưa gửi dự báo cho sale tới',
      body: 'Đã quá hạn cut-off 24h. Sản lượng đang dùng baseline — sẽ thiếu ~' + fmt.int(Math.round(c.avgDaily * 0.4)) + ' đơn/ngày nếu lift thực tế giống tháng trước.',
      actor: 'AM',
      action: { label: 'Ping ' + c.submittedBy.split('@')[0], icon: 'mail' },
    });
  }
  // Pending approvals
  if (c.pendingApprovals >= 3) {
    out.push({
      severity: 'WARNING', icon: 'check',
      title: c.pendingApprovals + ' yêu cầu chờ duyệt vượt 2× baseline',
      body: 'Cần Planner duyệt sớm để dự báo ổn định trước cut-off ca sáng mai.',
      actor: 'Planner',
      action: { label: 'Mở phê duyệt', icon: 'check' },
    });
  } else if (c.pendingApprovals > 0) {
    out.push({
      severity: 'INFO', icon: 'check',
      title: c.pendingApprovals + ' yêu cầu chờ duyệt',
      body: 'Trong ngưỡng bình thường, nhưng nên xử lý trong 4h.',
      actor: 'Planner',
      action: { label: 'Mở phê duyệt', icon: 'check' },
    });
  }
  // High volatility
  if (c.volatility >= 0.30) {
    out.push({
      severity: 'WARNING', icon: 'spark',
      title: 'Biến động cao (' + (c.volatility * 100).toFixed(0) + '% CoV)',
      body: 'Sản lượng dao động lớn ngày-qua-ngày. Nên xác nhận với KAM trước mỗi đợt sale; cân nhắc tăng buffer 8-12%.',
      actor: 'AM',
      action: { label: 'Đề xuất buffer', icon: 'sliders' },
    });
  }
  // High MoM growth
  if (c.momPct >= 15) {
    out.push({
      severity: 'INFO', icon: 'arrowUp',
      title: 'Tăng trưởng mạnh (+' + c.momPct + '% MoM)',
      body: 'Khách đang trên đà tăng. Đề xuất review tier và năng suất mặc định trong vòng 2 tuần.',
      actor: 'AM',
      action: { label: 'Mở Tùy chỉnh', icon: 'cog' },
    });
  }
  // Sharp MoM decline
  if (c.momPct <= -10) {
    out.push({
      severity: 'WARNING', icon: 'arrowDown',
      title: 'Giảm ' + Math.abs(c.momPct) + '% MoM',
      body: 'Cần kiểm tra với KAM nguyên nhân (kế hoạch bán, hết hàng, chuyển kênh) trước cut-off forecast.',
      actor: 'AM',
      action: { label: 'Ping KAM', icon: 'mail' },
    });
  }
  // Predicted sale not confirmed
  if (c.predictedNextSale) {
    out.push({
      severity: 'INFO', icon: 'spark',
      title: 'Hệ thống dự đoán sale ngày ' + fmt.shortDate(c.predictedNextSale.date),
      body: c.predictedNextSale.note + ' Confidence ' + Math.round(c.predictedNextSale.confidence * 100) + '%.',
      actor: 'AM',
      action: { label: 'Promote / Hủy', icon: 'check' },
    });
  }
  return out;
}

Object.assign(window, { CustomerDetailPage, CustomerPlanTab, buildCustomerSeries, computeAlerts });
