// CompliancePage.jsx — full-page assembly of the AEO Compliance view.
// Rebuilt from frontend/src/components/pages/CompliancePage.js with
// inline-rendered chart placeholders that match Recharts visually.

const {
  COLORS: PC, statusColor: pStatusColor, pctDisplay: pPct, cAlpha: pAlpha,
  CompPageHeader, CompButton, TeamTabs,
  MetricHealthCard, DeviceTable, DeviceTableToolbar, DeviceTableHeader, DeviceRow, CompEmpty,
  ChartCard, ChartLegend, RollbackDialog, RollbackToast, CompIcon: PIcon,
} = window.COMP;

const { useState: useCompPageState } = React;

/* ── Sample data — what summary + items endpoints look like ── */
const SAMPLE_FAMILIES = [
  {
    metricId: 'VM-CRITICAL', category: 'Vulnerability Management', target: 0.95, worstStatus: 'Below 15% of Target',
    entries: [
      { metric_id: 'VM-CRITICAL', priority: 'P1',  compliance_pct: 0.74, status: 'Below 15% of Target' },
      { metric_id: 'VM-CRITICAL', priority: 'P2',  compliance_pct: 0.91, status: 'Within 15% of Target' },
    ],
  },
  {
    metricId: 'AUTH-MFA', category: 'Access & MFA', target: 0.98, worstStatus: 'Within 15% of Target',
    entries: [{ metric_id: 'AUTH-MFA', compliance_pct: 0.94, status: 'Within 15% of Target' }],
  },
  {
    metricId: 'LOG-COVERAGE', category: 'Logging & Monitoring', target: 0.90, worstStatus: 'Meets/Exceeds Target',
    entries: [{ metric_id: 'LOG-COVERAGE', compliance_pct: 0.97, status: 'Meets/Exceeds Target' }],
  },
  {
    metricId: 'EOL-OS', category: 'End-of-Life OS', target: 1.00, worstStatus: 'Below 15% of Target',
    entries: [{ metric_id: 'EOL-OS', compliance_pct: 0.62, status: 'Below 15% of Target' }],
  },
  {
    metricId: 'EDR-DEPLOY', category: 'Endpoint Protection', target: 0.95, worstStatus: 'Meets/Exceeds Target',
    entries: [{ metric_id: 'EDR-DEPLOY', compliance_pct: 0.96, status: 'Meets/Exceeds Target' }],
  },
];

const SAMPLE_DEVICES = [
  { hostname: 'app-prod-04.steam.internal', ip: '10.42.18.4',  type: 'Linux server',  failingMetrics: [{ metric_id: 'VM-CRITICAL', category: 'Vulnerability Management' }, { metric_id: 'EOL-OS', category: 'End-of-Life OS' }], seenCount: 5, hasNotes: true },
  { hostname: 'db-staging-01.steam.internal', ip: '10.42.20.11', type: 'Linux server',  failingMetrics: [{ metric_id: 'VM-CRITICAL', category: 'Vulnerability Management' }],                                                                                                seenCount: 2, hasNotes: false },
  { hostname: 'fileshare-02.steam.internal', ip: '10.42.16.32', type: 'Windows server', failingMetrics: [{ metric_id: 'AUTH-MFA', category: 'Access & MFA' }],                                                                                                                  seenCount: 1, hasNotes: false },
  { hostname: 'jumpbox-east.steam.internal', ip: '10.42.4.7',   type: 'Linux server',  failingMetrics: [{ metric_id: 'AUTH-MFA', category: 'Access & MFA' }, { metric_id: 'VM-CRITICAL', category: 'Vulnerability Management' }],                                              seenCount: 4, hasNotes: true },
  { hostname: 'legacy-billing.steam.internal', ip: '10.42.8.18', type: 'Windows server', failingMetrics: [{ metric_id: 'EOL-OS', category: 'End-of-Life OS' }],                                                                                                                seenCount: 7, hasNotes: false },
];

/* ── Inline chart visuals — semantic stand-ins for Recharts. ── */
function NetworkScoreChart() {
  const points = [82, 84, 81, 86, 85, 87, 88];
  return (
    <ChartSvg>
      <Line points={points} color={PC.teal} fill={pAlpha(PC.teal, 0.15)} />
      <YAxisLabels labels={['100%', '80%', '60%']} />
    </ChartSvg>
  );
}
function StatusDistributionChart() {
  const data = [
    { meets: 62, within: 22, below: 16 },
    { meets: 65, within: 20, below: 15 },
    { meets: 67, within: 21, below: 12 },
    { meets: 72, within: 18, below: 10 },
  ];
  return <StackedBars data={data} keys={['meets', 'within', 'below']} colors={[PC.green, PC.amber, PC.red]} />;
}
function TeamHealthChart() {
  return (
    <ChartSvg>
      <Line points={[78, 80, 79, 83, 85, 88]} color={PC.teal} />
      <Line points={[68, 70, 73, 71, 74, 76]} color={PC.amber} />
    </ChartSvg>
  );
}
function NewRecurringResolvedChart() {
  const data = [
    { new_count: 12, recurring_count: 7, resolved_count: -10 },
    { new_count: 8,  recurring_count: 9, resolved_count: -14 },
    { new_count: 14, recurring_count: 5, resolved_count: -8 },
    { new_count: 9,  recurring_count: 6, resolved_count: -12 },
  ];
  return (
    <ChartSvg>
      <ChartLegend items={[
        { label: 'New', color: PC.red },
        { label: 'Recurring', color: PC.amber },
        { label: 'Resolved', color: PC.green },
      ]} />
      <StackedBars data={data} keys={['new_count', 'recurring_count', 'resolved_count']} colors={[PC.red, PC.amber, PC.green]} centered />
    </ChartSvg>
  );
}
function AvgDaysToResolveChart() {
  const rows = [
    { label: 'AUTH-MFA',     v: 4 },
    { label: 'VM-CRITICAL',  v: 12 },
    { label: 'EOL-OS',       v: 28 },
    { label: 'EDR-DEPLOY',   v: 6 },
  ];
  return <HorizontalBars rows={rows} max={32} color={PC.teal} unit="days" />;
}
function PersistentFindingsChart() {
  const rows = [
    { label: 'legacy-billing',  v: 7 },
    { label: 'app-prod-04',     v: 5 },
    { label: 'jumpbox-east',    v: 4 },
    { label: 'db-staging-01',   v: 2 },
  ];
  return <HorizontalBars rows={rows} max={8} color={PC.amber} unit="cycles" />;
}

/* Tiny SVG primitives — flat, deterministic, no library. */
function ChartSvg({ children, height = 180 }) {
  return (
    <div style={{ position: 'relative', width: '100%', height }}>
      {children}
    </div>
  );
}
function Line({ points, color, fill }) {
  const max = Math.max(...points);
  const min = Math.min(...points) * 0.85;
  const range = max - min || 1;
  const w = 100, h = 100;
  const step = w / (points.length - 1);
  const path = points.map((v, i) => `${i === 0 ? 'M' : 'L'} ${i * step} ${h - ((v - min) / range) * h}`).join(' ');
  const fillPath = path + ` L ${w} ${h} L 0 ${h} Z`;
  return (
    <svg width="100%" height="100%" viewBox={`0 0 ${w} ${h}`} preserveAspectRatio="none" style={{ overflow: 'visible' }}>
      {fill && <path d={fillPath} fill={fill} />}
      <path d={path} fill="none" stroke={color} strokeWidth="1.5" />
      {points.map((v, i) => (
        <circle key={i} cx={i * step} cy={h - ((v - min) / range) * h} r="1.5" fill={color} />
      ))}
    </svg>
  );
}
function YAxisLabels({ labels }) {
  return (
    <div style={{
      position: 'absolute', top: 0, bottom: 0, left: -2,
      display: 'flex', flexDirection: 'column', justifyContent: 'space-between',
      fontFamily: 'var(--font-mono)', fontSize: 9, color: 'var(--fg-disabled)',
      pointerEvents: 'none',
    }}>
      {labels.map(l => <span key={l}>{l}</span>)}
    </div>
  );
}
function StackedBars({ data, keys, colors, centered = false }) {
  const total = (d) => keys.reduce((s, k) => s + Math.abs(d[k]), 0);
  const maxTotal = Math.max(...data.map(total));
  return (
    <div style={{ display: 'flex', alignItems: centered ? 'center' : 'flex-end', gap: 12, height: '100%', paddingTop: 8 }}>
      {data.map((d, i) => {
        const segs = keys.map((k, ki) => ({ v: d[k], color: colors[ki], k }));
        return (
          <div key={i} style={{ flex: 1, display: 'flex', flexDirection: 'column', alignItems: 'center', height: '100%' }}>
            <div style={{ flex: 1, width: '100%', display: 'flex', flexDirection: 'column', justifyContent: 'flex-end' }}>
              {segs.map((s, si) => (
                <div key={si} style={{
                  width: '100%', height: `${(Math.abs(s.v) / maxTotal) * 100}%`,
                  background: s.color, opacity: 0.85,
                  borderTopLeftRadius: si === 0 ? 2 : 0,
                  borderTopRightRadius: si === 0 ? 2 : 0,
                }} />
              ))}
            </div>
          </div>
        );
      })}
    </div>
  );
}
function HorizontalBars({ rows, max, color, unit }) {
  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 8, paddingTop: 8 }}>
      {rows.map(r => (
        <div key={r.label} style={{ display: 'grid', gridTemplateColumns: '120px 1fr 50px', gap: 8, alignItems: 'center' }}>
          <span style={{ fontFamily: 'var(--font-mono)', fontSize: 11, color: 'var(--fg-2)', textAlign: 'right' }}>{r.label}</span>
          <div style={{ height: 14, background: 'rgba(255,255,255,0.04)', borderRadius: 3, overflow: 'hidden' }}>
            <div style={{ width: `${(r.v / max) * 100}%`, height: '100%', background: color, opacity: 0.85, borderRadius: 3 }} />
          </div>
          <span style={{ fontFamily: 'var(--font-mono)', fontSize: 11, color, fontWeight: 600 }}>{r.v} {unit}</span>
        </div>
      ))}
    </div>
  );
}

/* ── Page assembly ── */
function CompliancePage() {
  const [team, setTeam] = useCompPageState('STEAM');
  const [tab, setTab] = useCompPageState('active');
  const [filter, setFilter] = useCompPageState(null);
  const [search, setSearch] = useCompPageState('');
  const [selected, setSelected] = useCompPageState(null);
  const [rollback, setRollback] = useCompPageState(null);

  const filteredDevices = SAMPLE_DEVICES
    .filter(d => !filter || d.failingMetrics.some(m => filter.includes(m.metric_id)))
    .filter(d => !search || d.hostname.toLowerCase().includes(search.toLowerCase()));

  return (
    <div data-screen-label="01 Compliance" style={{
      position: 'relative',
      padding: 32, minHeight: '100vh', background: 'var(--bg-page)',
      fontFamily: 'var(--font-display)',
    }}>
      <CompPageHeader
        lastReport="2026-04-21"
        networkScore="88%"
        verticalScore="84%"
        isAdmin
        onRollback={() => setRollback('confirm')}
      />

      <TeamTabs teams={['STEAM', 'ACCESS-ENG']} active={team} onChange={setTeam} />

      {/* Metric Health */}
      <div style={{ marginBottom: 24 }}>
        <div style={{
          fontFamily: 'var(--font-mono)', fontSize: 10, fontWeight: 600,
          color: 'var(--fg-disabled)', textTransform: 'uppercase', letterSpacing: '0.1em',
          marginBottom: 10,
        }}>
          Metric Health — click to filter
          {filter && (
            <button onClick={() => setFilter(null)} style={{
              marginLeft: 12, color: PC.teal, background: 'none', border: 'none',
              cursor: 'pointer', fontSize: 10, fontFamily: 'var(--font-mono)',
            }}>× clear filter</button>
          )}
        </div>
        <div style={{ display: 'flex', gap: 10, flexWrap: 'wrap' }}>
          {SAMPLE_FAMILIES.map(family => {
            const ids = family.entries.map(e => e.metric_id);
            const isActive = filter !== null && filter.length === ids.length && ids.every(id => filter.includes(id));
            return (
              <div key={family.metricId} style={{ display: 'flex', flex: '1 1 0', minWidth: 160 }}>
                <MetricHealthCard
                  family={family}
                  active={isActive}
                  onClick={() => setFilter(isActive ? null : ids)}
                  onInfoClick={() => {}}
                />
              </div>
            );
          })}
        </div>
      </div>

      {/* Charts */}
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 16, marginBottom: 24 }}>
        <ChartCard title="Network Compliance" subtitle="Trailing 7 days">
          <NetworkScoreChart />
        </ChartCard>
        <ChartCard title="Status Distribution" subtitle="Last 4 cycles">
          <StatusDistributionChart />
        </ChartCard>
        <ChartCard title="Team Health" subtitle="STEAM vs ACCESS-ENG">
          <TeamHealthChart />
        </ChartCard>
        <ChartCard title="New / Recurring / Resolved" subtitle="Per cycle" height={200}>
          <NewRecurringResolvedChart />
        </ChartCard>
        <ChartCard title="Avg Days to Resolve" subtitle="By metric">
          <AvgDaysToResolveChart />
        </ChartCard>
        <ChartCard title="Most Persistent Findings" subtitle="By cycles seen">
          <PersistentFindingsChart />
        </ChartCard>
      </div>

      {/* Device table */}
      <DeviceTable>
        <DeviceTableToolbar
          tab={tab} onTabChange={setTab}
          count={filteredDevices.length}
          search={search} onSearchChange={e => setSearch(e.target.value)}
        />
        <DeviceTableHeader />
        {filteredDevices.length === 0 ? (
          <CompEmpty>No non-compliant devices match the current filter</CompEmpty>
        ) : (
          filteredDevices.map(d => (
            <DeviceRow
              key={d.hostname}
              hostname={d.hostname} ip={d.ip} type={d.type}
              failingMetrics={d.failingMetrics}
              seenCount={d.seenCount} hasNotes={d.hasNotes}
              selected={selected === d.hostname}
              onClick={() => setSelected(selected === d.hostname ? null : d.hostname)}
            />
          ))
        )}
      </DeviceTable>

      {rollback === 'confirm' && (
        <RollbackDialog
          reportLabel="2026-04-21"
          onCancel={() => setRollback(null)}
          onConfirm={() => setRollback('toast')}
        />
      )}
      {rollback === 'toast' && (
        <RollbackToast
          tone="success"
          message="Upload rolled back"
          detail="42 items deleted, 18 reactivated"
          onDismiss={() => setRollback(null)}
        />
      )}
    </div>
  );
}

window.COMP_PAGE = { CompliancePage };
