// screens-home.jsx
//
// Two routes share this file:
//
// • Home — the launcher. Big-button entry into each section of the MAM.
//   This is what you see when you log in / hit /. Resembles the original
//   first-version landing page.
//
// • Dashboard — the operations view (recent activity, job queue, cluster,
//   live recorders). Reachable from the sidebar or from the Home launcher.
//   This is the React component that used to be `Home`.

function Home({ navigate }) {
  // Pull live counts so the tile subtitles ("34 assets", "0 live", "3 running")
  // reflect what's actually in the DB right now, not a stale boot-time cache.
  const [cards, setCards] = React.useState({});
  React.useEffect(() => {
    let cancelled = false;
    const load = () => {
      window.ZAMPP_API.fetch('/metrics/home?hours=1')
        .then(d => { if (!cancelled) setCards(d?.cards || {}); })
        .catch(() => {});
    };
    load();
    const t = setInterval(load, 30_000);
    return () => { cancelled = true; clearInterval(t); };
  }, []);

  const { ASSETS = [], RECORDERS = [], JOBS = [], NODES = [] } = window.ZAMPP_DATA || {};
  const assetsTotal  = cards.assets?.total      ?? ASSETS.length;
  const liveCount    = cards.recorders?.live    ?? RECORDERS.filter(r => r.status === 'recording').length;
  const totalRecs    = cards.recorders?.total   ?? RECORDERS.length;
  const runningJobs  = cards.jobs?.running      ?? JOBS.filter(j => j.status === 'running' || j.status === 'queued').length;
  const failedJobs   = cards.jobs?.failed_total ?? JOBS.filter(j => j.status === 'failed').length;
  const nodesOnline  = cards.cluster?.online    ?? NODES.filter(n => n.status === 'online' || n.online === true).length;
  const nodesTotal   = cards.cluster?.total     ?? NODES.length;

  const tiles = [
    {
      id: 'library',
      label: 'Library',
      icon: 'library',
      tone: 'accent',
      sub: assetsTotal > 0 ? assetsTotal.toLocaleString() + ' assets' : 'No assets yet',
      desc: 'Browse projects, bins, and assets. Hover-scrub previews.',
    },
    {
      id: 'recorders',
      label: 'Recorders',
      icon: 'record',
      tone: 'live',
      sub: liveCount > 0
        ? liveCount + ' live · ' + totalRecs + ' configured'
        : totalRecs + ' configured',
      desc: 'SDI · SRT · RTMP ingest. Start, stop, schedule.',
    },
    {
      id: 'editor',
      label: 'Editor',
      icon: 'editor',
      tone: 'purple',
      sub: 'Beta',
      desc: 'Timeline editor with cross-clip preview and render queue.',
    },
    {
      id: 'jobs',
      label: 'Jobs',
      icon: 'jobs',
      tone: failedJobs > 0 ? 'warn' : 'success',
      sub: runningJobs > 0
        ? runningJobs + ' running' + (failedJobs > 0 ? ' · ' + failedJobs + ' failed' : '')
        : (failedJobs > 0 ? failedJobs + ' failed' : 'All clear'),
      desc: 'Proxy + thumbnail queue. Retry failed jobs.',
    },
    {
      id: 'settings',
      label: 'Settings',
      icon: 'settings',
      tone: 'neutral',
      sub: 'S3 · Encoder · Growing files',
      desc: 'Storage, proxy encoder, capture SDK, growing-file mode.',
    },
  ];

  const clusterHealthy = !nodesTotal || nodesOnline >= nodesTotal;

  return (
    <div className="launcher">
      <div className="launcher-inner">
        <div className="launcher-hero">
          <img
            className="launcher-logo"
            src="img/dragon-logo.png"
            alt="Dragonflight"
            draggable="false"
          />
          <h1 className="launcher-wordmark">DRAGONFLIGHT</h1>
          <p className="launcher-tagline">
            Self-hosted broadcast media-asset management
          </p>
        </div>

        <div className="launcher-grid">
          {tiles.map(t => (
            <button
              key={t.id}
              className={'launcher-tile tone-' + t.tone}
              onClick={() => navigate(t.id)}
            >
              <span className="launcher-tile-icon">
                <Icon name={t.icon} size={26} />
              </span>
              <span className="launcher-tile-label">{t.label}</span>
              <span className="launcher-tile-sub">{t.sub}</span>
              <span className="launcher-tile-desc">{t.desc}</span>
              <span className="launcher-tile-arrow">
                <Icon name="arrowRight" size={14} />
              </span>
            </button>
          ))}

          <button
            className="launcher-tile tone-ghost launcher-tile-secondary"
            onClick={() => navigate('dashboard')}
          >
            <span className="launcher-tile-icon">
              <Icon name="home" size={22} />
            </span>
            <span className="launcher-tile-label">Dashboard</span>
            <span className="launcher-tile-sub">Operations view</span>
            <span className="launcher-tile-desc">
              Recent activity, job queue, cluster health.
            </span>
            <span className="launcher-tile-arrow">
              <Icon name="arrowRight" size={14} />
            </span>
          </button>
        </div>

        <div className="launcher-status">
          <span className="launcher-status-pip">
            <span
              className="dot"
              style={{ background: clusterHealthy ? 'var(--success)' : 'var(--warning)' }}
            />
            {clusterHealthy ? 'cluster healthy' : 'cluster degraded'}
            <span className="muted">· {nodesOnline}/{nodesTotal || 0} node{nodesTotal === 1 ? '' : 's'}</span>
          </span>
          {liveCount > 0 && (
            <span className="launcher-status-pip live">
              <span className="dot" style={{ background: 'var(--live)' }} />
              {liveCount} recorder{liveCount === 1 ? '' : 's'} live
            </span>
          )}
        </div>
      </div>
    </div>
  );
}

function Dashboard({ navigate }) {
  const { RECORDERS, JOBS, ASSETS, NODES } = window.ZAMPP_DATA;

  // Live (current-state) data from the boot-time data load
  const liveRecorders = RECORDERS.filter(r => r.status === 'recording').slice(0, 4);
  const runningJobs   = JOBS.filter(j => j.status === 'running' || j.status === 'queued');
  const recentAssets  = [...ASSETS].sort((a, b) => new Date(b.created_at) - new Date(a.created_at)).slice(0, 6);

  // Real historic sparklines from /metrics/home — buckets the last 24h.
  const [metrics, setMetrics] = React.useState(null);
  React.useEffect(() => {
    let cancelled = false;
    const load = () => {
      window.ZAMPP_API.fetch('/metrics/home?hours=24')
        .then(d => { if (!cancelled) setMetrics(d); })
        .catch(() => {});
    };
    load();
    const t = setInterval(load, 30_000);
    return () => { cancelled = true; clearInterval(t); };
  }, []);

  const cards = metrics?.cards || {};
  const vals = (s) => Array.isArray(s) ? s.map(p => p.v) : [];

  // Card values come from /metrics so that "Library" reflects what's in the
  // DB right now, not whatever ZAMPP_DATA happens to be cached as on first load.
  const assetsTotal = cards.assets?.total ?? ASSETS.length;
  const liveCount   = cards.recorders?.live ?? liveRecorders.length;
  const totalRecs   = cards.recorders?.total ?? RECORDERS.length;
  const runningCount = cards.jobs?.running ?? runningJobs.length;
  const doneCount   = cards.jobs?.done_total ?? JOBS.filter(j => j.status === 'done').length;
  const failedCount = cards.jobs?.failed_total ?? JOBS.filter(j => j.status === 'failed').length;
  const nodesOnline = cards.cluster?.online ?? NODES.filter(n => n.status === 'online' || n.online === true).length;
  const nodesTotal  = cards.cluster?.total ?? NODES.length;

  // Sum the most recent hour of each bucketed series for the delta line so
  // the "+N this hour" hint always reflects the latest bucket.
  const sumWindow = (series) => (Array.isArray(series) ? series.reduce((a, p) => a + p.v, 0) : 0);

  return (
    <div className="page">
      <div className="dash-stat-row">
        <div className="dash-stat" onClick={() => navigate('library')} style={{ cursor: 'pointer' }}>
          <div className="dash-stat-top">
            <span className="dash-stat-label">Library</span>
            <Icon name="library" size={13} className="dash-stat-ico" />
          </div>
          <div className="dash-stat-mono">{assetsTotal.toLocaleString()}</div>
          <div className="dash-stat-sub">
            {sumWindow(cards.assets?.series) > 0
              ? '+' + sumWindow(cards.assets?.series) + ' in 24h'
              : 'total assets'}
          </div>
          <DashSparkline data={vals(cards.assets?.series)} color="#5B7CFA" />
        </div>
        <div className="dash-stat" onClick={() => navigate('recorders')} style={{ cursor: 'pointer' }}>
          <div className="dash-stat-top">
            <span className="dash-stat-label">Live feeds</span>
            <Icon name="record" size={13} className="dash-stat-ico" />
          </div>
          <div className="dash-stat-mono">{liveCount}</div>
          <div className="dash-stat-sub">{totalRecs} configured</div>
          <DashSparkline data={vals(cards.recorders?.series)} color="#2DD4A8" />
        </div>
        <div className="dash-stat" onClick={() => navigate('jobs')} style={{ cursor: 'pointer' }}>
          <div className="dash-stat-top">
            <span className="dash-stat-label">Jobs</span>
            <Icon name="jobs" size={13} className="dash-stat-ico" />
          </div>
          <div className="dash-stat-mono">{runningCount}<span className="dash-stat-mono-sub"> / {doneCount}</span></div>
          <div className="dash-stat-sub" style={{ color: failedCount > 0 ? 'var(--warning)' : '' }}>
            {failedCount > 0 ? failedCount + ' failed' : 'All clear'}
            {sumWindow(cards.jobs?.series_done) > 0 && (
              <> · {sumWindow(cards.jobs?.series_done)} in 24h</>
            )}
          </div>
          <DashSparkline data={vals(cards.jobs?.series_done)} color="#B57CFA" />
        </div>
        <div className="dash-stat" onClick={() => navigate('cluster')} style={{ cursor: 'pointer' }}>
          <div className="dash-stat-top">
            <span className="dash-stat-label">Cluster</span>
            <Icon name="hdd" size={13} className="dash-stat-ico" />
          </div>
          <div className="dash-stat-mono">{nodesOnline}<span className="dash-stat-mono-sub"> / {nodesTotal}</span></div>
          <div className="dash-stat-sub">nodes online</div>
          <DashSparkline data={vals(cards.cluster?.series)} color="#F5A623" />
        </div>
      </div>

      <div className="home-grid">
        <div>
          {liveRecorders.length > 0 && (
            <>
              <SectionHead title="Live now" onMore={() => navigate('recorders')} moreLabel="All recorders" />
              <div className="live-feed-grid">
                {liveRecorders.map(r => (
                  <div key={r.id} className="live-feed-tile" onClick={() => navigate('recorders')}>
                    <div className="live-feed-tile-badge"><span className="badge live">REC</span></div>
                    {r.live_asset_id
                      ? <HlsPreview assetId={r.live_asset_id} />
                      : <FauxFrame />}
                    <div className="live-feed-tile-label">
                      <span className="name">{r.name}</span>
                      {r.source && <span className="source">{r.source}</span>}
                      <span className="time">{r.elapsed}</span>
                    </div>
                    {r.project && (
                      <div className="live-feed-tile-project">
                        <span className="live-feed-project-dot" style={{ background: r.project_color || 'var(--text-3)' }} />
                        <span>{r.project}</span>
                      </div>
                    )}
                  </div>
                ))}
              </div>
              <div style={{ height: 16 }} />
            </>
          )}

          <SectionHead title="Recently added" onMore={() => navigate('library')} moreLabel="All assets" />
          <div className="activity-feed">
            {recentAssets.length === 0 ? (
              <div className="dash-empty">No assets yet.</div>
            ) : recentAssets.map(a => (
              <div key={a.id} className="activity-row">
                <div className="activity-icon record">
                  <Icon name={a.type === 'audio' ? 'audio' : 'video'} size={12} />
                </div>
                <div className="activity-text">
                  <span className="target">{a.name}</span>
                  {a.project && <> in <strong>{a.project}</strong></>}
                </div>
                <div className="activity-meta">
                  {a.duration && <span className="activity-dur">{a.duration}</span>}
                  {a.res && <span className="activity-res">{a.res}</span>}
                </div>
                <div className="activity-time">{a.updated}</div>
              </div>
            ))}
          </div>
        </div>

        <div>
          <SectionHead title="Job queue" onMore={() => navigate('jobs')} moreLabel="View all" />
          <div className="panel" style={{ padding: 4 }}>
            {JOBS.length === 0
              ? <div className="dash-empty-panel">No jobs.</div>
              : JOBS.slice(0, 5).map(j => <MiniJobRow key={j.id} job={j} />)}
          </div>

          <div style={{ height: 16 }} />
          <SectionHead title="Cluster" onMore={() => navigate('cluster')} moreLabel="View all" />
          <div className="panel" style={{ padding: 4 }}>
            {NODES.length === 0
              ? <div className="dash-empty-panel">No nodes found.</div>
              : NODES.slice(0, 4).map(n => {
                  const nodeId = n.id || n.hostname || n.name || 'node';
                  const isOnline = n.status === 'online' || n.online === true;
                  const cpuPct = n.cpu_percent ?? n.cpu ?? n.cpu_usage ?? null;
                  const memRaw = n.memory_used_gb ?? n.mem ?? (n.mem_used_mb != null ? n.mem_used_mb / 1024 : null);
                  const memGb = memRaw != null ? Number(memRaw) : null;
                  const memTotal = n.memory_total_gb ?? n.mem_total_gb ?? null;
                  const memPct = memGb && memTotal ? Math.round((memGb / memTotal) * 100) : null;
                  return (
                    <div key={nodeId} className="cluster-node-row">
                      <StatusDot status={isOnline ? 'online' : 'offline'} />
                      <span className="cluster-node-name">{nodeId}</span>
                      <span className="cluster-node-spacer" />
                      {cpuPct != null && (
                        <span className="cluster-node-metric">
                          <span className="cluster-node-metric-label">CPU</span>
                          <span className="cluster-node-bar">
                            <span className="cluster-node-bar-fill" style={{ width: Math.round(cpuPct) + '%', background: cpuPct > 80 ? 'var(--warning)' : 'var(--text-3)' }} />
                          </span>
                          <span className="cluster-node-metric-val">{Math.round(cpuPct)}%</span>
                        </span>
                      )}
                      {memGb != null && (
                        <span className="cluster-node-metric">
                          <span className="cluster-node-metric-label">MEM</span>
                          <span className="cluster-node-bar">
                            <span className="cluster-node-bar-fill" style={{ width: (memPct || Math.round((memGb / 32) * 100)) + '%', background: (memPct || 0) > 85 ? 'var(--warning)' : 'var(--text-3)' }} />
                          </span>
                          <span className="cluster-node-metric-val">{memGb < 1 ? Math.round(memGb * 1024) + 'MB' : memGb.toFixed(1) + 'GB'}</span>
                        </span>
                      )}
                    </div>
                  );
                })}
          </div>
        </div>
      </div>
    </div>
  );
}

function DashSparkline({ data, color }) {
  if (!data || data.length < 2) return <div className="dash-sparkline" />;
  const max = Math.max(...data, 1);
  const min = Math.min(...data, 0);
  const range = max - min || 1;
  const h = 24;
  const w = 80;
  const step = w / (data.length - 1);
  const pts = data.map((d, i) => (i * step) + ',' + (h - ((d - min) / range) * h)).join(' ');
  const area = '0,' + h + ' ' + pts + ' ' + w + ',' + h;
  return (
    <div className="dash-sparkline">
      <svg viewBox={'0 0 ' + w + ' ' + h} preserveAspectRatio="none" style={{ width: '100%', height: h, display: 'block' }}>
        <polygon points={area} fill={color} opacity="0.12" />
        <polyline points={pts} fill="none" stroke={color} strokeWidth="1.2" />
      </svg>
    </div>
  );
}

function SectionHead({ title, onMore, moreLabel = 'View all' }) {
  return (
    <div style={{ display: 'flex', alignItems: 'center', padding: '16px 0 10px', gap: 12 }}>
      <div style={{ fontSize: 13, fontWeight: 600, letterSpacing: '-0.01em', whiteSpace: 'nowrap' }}>{title}</div>
      {onMore && (
        <button className="btn ghost sm" style={{ marginLeft: 'auto', whiteSpace: 'nowrap' }} onClick={onMore}>
          {moreLabel}<Icon name="arrowRight" size={11} />
        </button>
      )}
    </div>
  );
}

function MiniJobRow({ job }) {
  return (
    <div className="mini-job-row">
      <StatusDot status={job.status} />
      <div className="mini-job-body">
        <div className="mini-job-line1">
          <span className="mini-job-kind">{job.kind}</span>
          <span className="mini-job-sep">·</span>
          <span className="mini-job-asset">{job.asset}</span>
          {job.node && <span className="mini-job-node">on {job.node}</span>}
        </div>
        {job.status === 'running' && (
          <div className="mini-job-progress">
            <div className="mini-job-progress-fill" style={{ width: (job.progress || 0) + '%' }} />
            <span className="mini-job-pct">{job.progress || 0}%</span>
          </div>
        )}
        {job.status === 'failed' && <div className="mini-job-error">{job.error}</div>}
      </div>
      <div className="mini-job-right">
        {job.status === 'running' && job.eta ? job.eta : <span className={'badge ' + job.status}>{job.status}</span>}
      </div>
    </div>
  );
}

window.Home = Home;
window.Dashboard = Dashboard;
