// screens-ingest.jsx — Upload, Recorders, Capture, Monitors

/* ===== Upload ===== */
function Upload({ navigate }) {
  const [files, setFiles] = React.useState([]);
  const [project, setProject] = React.useState('');

  React.useEffect(() => {
    const { PROJECTS } = window.ZAMPP_DATA;
    if (PROJECTS.length > 0 && !project) setProject(PROJECTS[0].id);
  }, []);

  const handleDrop = (e) => {
    e.preventDefault();
    const dropped = Array.from(e.dataTransfer ? e.dataTransfer.files : e.target.files);
    const newFiles = dropped.map((f, i) => ({
      id: Date.now() + i, name: f.name,
      size: window.ZAMPP_API.fmtSize(f.size),
      file: f, progress: 0, status: 'queued',
    }));
    setFiles(prev => [...prev, ...newFiles]);
  };

  const { PROJECTS } = window.ZAMPP_DATA;

  return (
    <div className="page">
      <div className="page-header">
        <h1>Upload</h1>
        <span className="subtitle">Drop video, audio, or stills — we proxy and index automatically.</span>
      </div>
      <div className="page-body">
        <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 12, marginBottom: 20 }}>
          <div>
            <label className="field-label">Project</label>
            <div className="select-faux">
              <span>{PROJECTS.find(p => p.id === project)?.name || (PROJECTS.length ? PROJECTS[0].name : 'No projects')}</span>
              <Icon name="chevronDown" size={12} />
            </div>
          </div>
        </div>

        <div className="dropzone" onDrop={handleDrop} onDragOver={e => e.preventDefault()}
          onClick={() => { const i = document.createElement('input'); i.type='file'; i.multiple=true; i.onchange=handleDrop; i.click(); }}>
          <Icon name="upload" size={32} style={{ color: 'var(--text-3)' }} />
          <div style={{ fontSize: 15, fontWeight: 500 }}>Drop files here or click to browse</div>
          <div className="muted" style={{ fontSize: 12.5 }}>Video, audio, and image files</div>
          <div className="dropzone-formats">
            {['MOV', 'MP4', 'MXF', 'ProRes', 'DNxHR', 'WAV', 'AIFF'].map(f => <span key={f} className="badge outline">{f}</span>)}
          </div>
        </div>

        {files.length > 0 && (
          <div style={{ marginTop: 24 }}>
            <div style={{ fontSize: 13, fontWeight: 600, marginBottom: 12, display: 'flex', alignItems: 'center', gap: 8 }}>
              Queue <span className="badge neutral">{files.length}</span>
              <span style={{ flex: 1 }} />
              <button className="btn ghost sm" onClick={() => setFiles(f => f.filter(x => x.status !== 'done'))}>Clear done</button>
            </div>
            <div className="panel">
              {files.map(f => (
                <div key={f.id} className="upload-row">
                  <Icon name={f.name.match(/\.(wav|aif|mp3)$/i) ? 'audio' : 'video'} size={16} style={{ color: 'var(--text-3)' }} />
                  <div style={{ flex: 1, minWidth: 0 }}>
                    <div style={{ display: 'flex', gap: 8, alignItems: 'center' }}>
                      <span style={{ fontWeight: 500, fontSize: 12.5 }}>{f.name}</span>
                      <span className="muted" style={{ fontSize: 11, fontFamily: 'var(--font-mono)' }}>{f.size}</span>
                    </div>
                    <div style={{ marginTop: 6, height: 4, background: 'var(--bg-3)', borderRadius: 99, overflow: 'hidden' }}>
                      <div style={{ width: f.progress + '%', height: '100%', background: f.status === 'done' ? 'var(--success)' : 'var(--accent)', transition: 'width 200ms' }} />
                    </div>
                  </div>
                  <span className="mono" style={{ fontSize: 11.5, color: 'var(--text-3)', minWidth: 60, textAlign: 'right' }}>
                    {f.status === 'done' ? '✓ done' : f.status === 'queued' ? 'queued' : Math.round(f.progress) + '%'}
                  </span>
                </div>
              ))}
            </div>
          </div>
        )}
      </div>
    </div>
  );
}

/* ===== Recorders ===== */
function Recorders({ navigate, onNew }) {
  const [recorders, setRecorders] = React.useState(window.ZAMPP_DATA.RECORDERS);

  // Poll every 10s for recorder status changes
  React.useEffect(() => {
    const refresh = () => {
      window.ZAMPP_API.fetch('/recorders')
        .then(raw => {
          const norm = (raw || []).map(r => {
            let elapsed = '—';
            if (r.status === 'recording' && r.started_at) {
              const s = Math.floor((Date.now() - new Date(r.started_at)) / 1000);
              elapsed = String(Math.floor(s/3600)).padStart(2,'0')+':'+String(Math.floor((s%3600)/60)).padStart(2,'0')+':'+String(s%60).padStart(2,'0');
            }
            const cfg = r.source_config || {};
            return { ...r, source: r.source_type||'—', url: cfg.url||cfg.address||r.source_type||'—', codec: r.recording_codec||'—', res: r.recording_resolution||'—', node: r.node_id||'primary', elapsed, bitrate:'—', health:100, audio:false };
          });
          window.ZAMPP_DATA.RECORDERS = norm;
          setRecorders(norm);
        })
        .catch(() => {});
    };
    const i = setInterval(refresh, 10000);
    return () => clearInterval(i);
  }, []);

  const liveCount = recorders.filter(r => r.status === 'recording').length;
  const errCount  = recorders.filter(r => r.status === 'error').length;

  return (
    <div className="page">
      <div className="page-header">
        <h1>Recorders</h1>
        <span className="subtitle">Live ingest from SRT, RTMP, and SDI sources</span>
        <div className="spacer" />
        {(liveCount > 0 || errCount > 0) && (
          <div className="status-pip">
            <span className="dot" />
            <span>{liveCount > 0 ? liveCount + ' recording' : ''}{errCount > 0 ? (liveCount > 0 ? ' · ' : '') + errCount + ' error' : ''}</span>
          </div>
        )}
        <button className="btn primary" onClick={onNew}><Icon name="plus" />New recorder</button>
      </div>
      <div className="page-body">
        {recorders.length === 0 ? (
          <div style={{ padding: 60, textAlign: 'center', color: 'var(--text-3)' }}>
            No recorders configured.
            <div style={{ marginTop: 12 }}><button className="btn primary" onClick={onNew}><Icon name="plus" />Add recorder</button></div>
          </div>
        ) : (
          <div className="recorders-list">
            {recorders.map(r => <RecorderRow key={r.id} recorder={r} onRefresh={() => { window.ZAMPP_API.fetch('/recorders').then(raw => setRecorders((raw||[]).map(x => { const cfg=x.source_config||{}; return {...x,source:x.source_type,url:cfg.url||cfg.address||x.source_type,codec:x.recording_codec,res:x.recording_resolution,node:x.node_id,elapsed:'—',bitrate:'—',health:100,audio:false}; }))).catch(()=>{}); }} />)}
          </div>
        )}
      </div>
    </div>
  );
}

function RecorderRow({ recorder, onRefresh }) {
  const isRec = recorder.status === 'recording';

  const toggle = () => {
    const action = isRec ? 'stop' : 'start';
    window.ZAMPP_API.fetch('/recorders/' + recorder.id + '/' + action, { method: 'POST' })
      .then(onRefresh).catch(() => {});
  };

  return (
    <div className={'recorder-row ' + recorder.status}>
      <div className="recorder-preview">
        {isRec
          ? <LiveStrip seed={recorder.id.length * 3} count={6} />
          : <div className="recorder-empty"><Icon name={recorder.status === 'error' ? 'alert' : 'video'} size={20} style={{ opacity: 0.4 }} /></div>}
      </div>
      <div className="recorder-info">
        <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
          <span style={{ fontWeight: 600, fontSize: 13 }}>{recorder.name}</span>
          <span className={'badge ' + badgeForStatus(recorder.status)}>
            <StatusDot status={recorder.status} /> {recorder.status.toUpperCase()}
          </span>
          <span className="badge outline">{recorder.source}</span>
        </div>
        <div className="recorder-sub mono">{recorder.url}</div>
        <div className="recorder-sub">
          <span>{recorder.codec}</span><span>·</span>
          <span>{recorder.res}</span>
        </div>
      </div>
      <div className="recorder-stats">
        <div className="recorder-stat">
          <div className="stat-label">Elapsed</div>
          <div className="stat-val mono">{recorder.elapsed}</div>
        </div>
        <div className="recorder-stat">
          <div className="stat-label">Status</div>
          <div className="stat-val"><StatusDot status={recorder.status} /></div>
        </div>
      </div>
      <div className="recorder-actions">
        {isRec
          ? <button className="btn danger sm" onClick={toggle}><span className="rec-dot" />Stop</button>
          : <button className="btn subtle sm" onClick={toggle}><span className="rec-dot" style={{ background: 'var(--live)' }} />Record</button>}
        <button className="icon-btn"><Icon name="more" /></button>
      </div>
    </div>
  );
}

function badgeForStatus(s) {
  return { recording: 'live', armed: 'accent', idle: 'neutral', error: 'danger', offline: 'neutral', stopped: 'neutral' }[s] || 'neutral';
}

function HealthBar({ value }) {
  const color = value > 80 ? 'var(--success)' : value > 40 ? 'var(--warning)' : 'var(--danger)';
  return (
    <div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
      <div style={{ width: 56, height: 5, background: 'var(--bg-3)', borderRadius: 99, overflow: 'hidden' }}>
        <div style={{ width: value + '%', height: '100%', background: color }} />
      </div>
      <span className="mono" style={{ fontSize: 11, color: 'var(--text-3)' }}>{value}%</span>
    </div>
  );
}

/* ===== Capture ===== */
function Capture({ navigate }) {
  const [devices, setDevices] = React.useState([]);
  const [activeIdx, setActiveIdx] = React.useState(0);

  React.useEffect(() => {
    window.ZAMPP_API.fetch('/cluster/devices/blackmagic')
      .then(devs => setDevices(devs || []))
      .catch(() => setDevices([]));
  }, []);

  if (devices.length === 0) {
    return (
      <div className="page">
        <div className="page-header">
          <h1>Capture</h1>
          <span className="subtitle">DeckLink SDI ingest</span>
          <div className="spacer" />
          <button className="btn ghost sm" onClick={() => window.ZAMPP_API.fetch('/cluster/devices/blackmagic').then(d => setDevices(d||[])).catch(()=>{})}
          ><Icon name="refresh" />Refresh</button>
        </div>
        <div className="page-body">
          <div style={{ padding: 60, textAlign: 'center', color: 'var(--text-3)' }}>
            No DeckLink devices found in cluster.
          </div>
        </div>
      </div>
    );
  }

  const active = devices[activeIdx] || devices[0];

  return (
    <div className="page">
      <div className="page-header">
        <h1>Capture</h1>
        <span className="subtitle">DeckLink SDI ingest — {devices.length} device{devices.length > 1 ? 's' : ''} in cluster</span>
        <div className="spacer" />
        <button className="btn ghost sm" onClick={() => window.ZAMPP_API.fetch('/cluster/devices/blackmagic').then(d => setDevices(d||[])).catch(()=>{})}><Icon name="refresh" />Refresh</button>
      </div>
      <div className="page-body">
        <div style={{ display: 'flex', gap: 12, flexWrap: 'wrap', marginBottom: 20 }}>
          {devices.map((d, i) => (
            <button key={i} className={'btn ' + (activeIdx === i ? 'primary' : 'ghost') + ' sm'} onClick={() => setActiveIdx(i)}>
              {d.model || d.device || 'DeckLink'} — {d.hostname}
            </button>
          ))}
        </div>
        <div className="panel" style={{ padding: 20 }}>
          <div style={{ display: 'flex', alignItems: 'center', gap: 12, marginBottom: 16 }}>
            <StatusDot status={active.online ? 'online' : 'offline'} />
            <div>
              <div style={{ fontWeight: 600 }}>{active.model || active.device || 'DeckLink'}</div>
              <div className="mono" style={{ fontSize: 11, color: 'var(--text-3)' }}>{active.hostname} · {active.ip_address}</div>
            </div>
          </div>
          <div style={{ color: 'var(--text-3)', fontSize: 12.5 }}>Connect a source and click Refresh to see port status.</div>
        </div>
      </div>
    </div>
  );
}

/* ===== Monitors ===== */
function Monitors({ navigate }) {
  const { RECORDERS } = window.ZAMPP_DATA;
  const [grid, setGrid] = React.useState(4);

  const videoFeeds = RECORDERS.filter(r => !r.audio);
  const audioFeeds = [
    { id: '__audio1', name: 'FOH Mix', kind: 'audio' },
    { id: '__audio2', name: 'PGM Bus', kind: 'audio' },
  ];
  const allFeeds = [
    ...videoFeeds.map(r => ({ ...r, kind: 'video' })),
    ...audioFeeds,
  ];
  const feeds = allFeeds.slice(0, grid * grid);

  return (
    <div className="page">
      <div className="page-header">
        <h1>Monitors</h1>
        <span className="subtitle">Multi-cam live monitoring</span>
        <div className="spacer" />
        <div className="tab-group">
          {[2, 3, 4].map(n => (
            <button key={n} className={grid === n ? 'active' : ''} onClick={() => setGrid(n)}>{n}×{n}</button>
          ))}
        </div>
      </div>
      <div className="page-body">
        <div className="monitors-grid" style={{ gridTemplateColumns: 'repeat(' + grid + ', 1fr)' }}>
          {feeds.map((f, i) => <MonitorTile key={f.id} feed={f} seed={i + 1} />)}
          {feeds.length === 0 && (
            <div style={{ gridColumn: '1/-1', padding: 60, textAlign: 'center', color: 'var(--text-3)' }}>No active feeds. Start a recorder to see live video here.</div>
          )}
        </div>
      </div>
    </div>
  );
}

function MonitorTile({ feed, seed }) {
  if (feed.kind === 'audio') {
    return (
      <div className="monitor-tile audio">
        <div style={{ flex: 1, display: 'grid', placeItems: 'center', padding: 24 }}>
          <Waveform seed={seed * 7} color="var(--accent)" />
        </div>
        <div style={{ display: 'flex', gap: 4, padding: '0 16px 16px', justifyContent: 'center' }}>
          <AudioMeter level={0.65} vertical />
          <AudioMeter level={0.78} vertical />
        </div>
        <div className="monitor-tile-label">
          <span className="badge live">LIVE</span>
          <span className="name">{feed.name}</span>
        </div>
      </div>
    );
  }
  return (
    <div className="monitor-tile">
      <FauxFrame />
      <div style={{ position: 'absolute', top: 8, left: 8, display: 'flex', gap: 6 }}>
        {feed.status === 'recording' && <span className="badge live">REC</span>}
        {feed.status === 'stopped'   && <span className="badge neutral">IDLE</span>}
        {feed.status === 'error'     && <span className="badge danger">ERR</span>}
      </div>
      <div className="monitor-tile-label">
        <span className="name">{feed.name}</span>
        {feed.elapsed && feed.elapsed !== '—' && <span className="time mono">{feed.elapsed}</span>}
      </div>
    </div>
  );
}

Object.assign(window, { Upload, Recorders, Capture, Monitors });
