/* global React */
const { useState, useEffect, useRef, useMemo } = React;

// ── Log line renderer ──────────────────────────────────────────────────────────
function LogLine({ ts, lvl, msg }) {
  const html = useMemo(() => (msg || '')
    .replace(/<kw>/g, '<span class="kw">').replace(/<\/kw>/g, '</span>')
    .replace(/<num>/g, '<span class="num">').replace(/<\/num>/g, '</span>')
    .replace(/<str>/g, '<span class="str">').replace(/<\/str>/g, '</span>')
  , [msg]);
  return (
    <div className={`log-line ${lvl || 'info'}`}>
      <span className="ts">{ts}</span>
      <span className="lvl">{lvl}</span>
      <span className="msg" dangerouslySetInnerHTML={{ __html: html }}/>
    </div>
  );
}

// ── Overview ───────────────────────────────────────────────────────────────────
function OverviewView({ status, runState, onRun, onStop, onJump }) {
  const isRunning = runState === 'running';
  const entities = status?.entities || [];
  const counts = status?.entityCounts || {};
  const lastSync = status?.history?.[0]?.ts;
  const lastSyncAge = lastSync ? formatAge(new Date(lastSync)) : '—';
  const filesCount = status?.filesCount || 0;
  const cron = status?.cronSchedule || '';

  const entityList = (PD_ENTITIES_DEFAULT || []).map(e => ({
    ...e,
    rows: counts[e.label] || counts[e.id] || 0,
    selected: entities.includes(e.label) || entities.includes(e.id) || entities.length === 0,
  }));

  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 24 }}>
      <div className="card" style={{ padding: 20, display: 'grid', gridTemplateColumns: '1fr auto', gap: 24, alignItems: 'center' }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 18 }}>
          <div style={{ width: 56, height: 56, borderRadius: 12, flexShrink: 0, background: isRunning ? 'var(--s-success-weak)' : 'var(--s-brand-weak)', color: isRunning ? 'var(--s-success)' : 'var(--s-link)', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
            {isRunning ? <span className="status-dot running" style={{ width: 14, height: 14 }}/> : <Icon d={I.database} size={26}/>}
          </div>
          <div>
            <div style={{ display: 'flex', alignItems: 'center', gap: 10, marginBottom: 4 }}>
              <h2 style={{ fontFamily: 'var(--s-font-display)', fontWeight: 400, fontSize: 22, letterSpacing: '-0.01em' }}>
                {isRunning ? 'Sync in progress' : 'All systems clear'}
              </h2>
              <Badge tone="success" dot>{isRunning ? 'Running' : 'Healthy'}</Badge>
            </div>
            <p style={{ fontSize: 13, color: 'var(--s-fg-2)', maxWidth: 540 }}>
              {isRunning ? 'Incremental sync running — streaming updates from Pipedrive into PostgreSQL.' : `Last sync ${lastSyncAge}${cron ? ' · next run on schedule ' + cron : ''}.`}
            </p>
          </div>
        </div>
        <div style={{ display: 'flex', gap: 8 }}>
          {isRunning
            ? <Button variant="secondary" destructive icon={<Icon d={I.stop} size={12}/>} onClick={onStop}>Stop sync</Button>
            : <Button variant="primary" icon={<Icon d={I.play} size={12}/>} onClick={onRun}>Run sync now</Button>
          }
          <Button variant="secondary" icon={<Icon d={I.list} size={13}/>} onClick={() => onJump('operations')}>View log</Button>
        </div>
      </div>

      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', gap: 12 }}>
        <Kpi label="Last sync" value={lastSyncAge} hint={lastSync ? new Date(lastSync).toLocaleString() : 'Never'} icon={<Icon d={I.clock}/>}/>
        <Kpi label="Entities configured" value={String(entities.length || entityList.filter(e => e.selected).length)} hint="selected entities" tone="accent" icon={<Icon d={I.database}/>}/>
        <Kpi label="Files in SharePoint" value={filesCount.toLocaleString()} hint="OneDrive sync" icon={<Icon d={I.cloud}/>}/>
        <Kpi label="Schedule" value={cron || 'Manual'} hint={cron ? 'auto-sync enabled' : 'no cron set'} icon={<Icon d={I.calendar}/>}/>
      </div>

      <div>
        <SectionHead title="Entities" hint={`${entities.length} configured · click to inspect`}
          right={<Button size="sm" variant="ghost" icon={<Icon d={I.settings} size={12}/>} onClick={() => onJump('config')}>Edit selection</Button>}/>
        <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(220px, 1fr))', gap: 10 }}>
          {entityList.filter(e => e.selected).map(e => (
            <button key={e.id} onClick={() => onJump('viewer', { entity: e.id })}
              style={{ textAlign: 'left', cursor: 'pointer', background: 'var(--s-bg-2)', border: '1px solid var(--s-border)', borderRadius: 'var(--s-r-md)', padding: 14, color: 'inherit', fontFamily: 'inherit', display: 'flex', flexDirection: 'column', gap: 8, transition: 'background var(--s-dur-fast) var(--s-ease)' }}
              onMouseEnter={ev => ev.currentTarget.style.background = 'var(--s-bg-3)'}
              onMouseLeave={ev => ev.currentTarget.style.background = 'var(--s-bg-2)'}>
              <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
                <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
                  <span style={{ color: 'var(--s-fg-3)', display: 'flex' }}><Icon d={I[e.icon] || I.database} size={14}/></span>
                  <span style={{ fontSize: 13, fontWeight: 500 }}>{e.label}</span>
                </div>
                <span className={`status-dot ${e.status === 'ok' ? 'success' : 'warning'}`}/>
              </div>
              <div style={{ display: 'flex', alignItems: 'baseline', gap: 6 }}>
                <span style={{ fontSize: 20, fontWeight: 600, fontFamily: 'var(--s-font-display)', letterSpacing: '-0.01em' }}>{e.rows.toLocaleString()}</span>
                <span style={{ fontSize: 11.5, color: 'var(--s-fg-3)' }}>rows</span>
              </div>
              {e.note && <div style={{ fontSize: 11, color: 'var(--s-warning)' }}>{e.note}</div>}
            </button>
          ))}
        </div>
      </div>

      {status?.history?.length > 0 && (
        <div>
          <SectionHead title="Recent runs" hint="Last 5" right={<Button size="sm" variant="ghost" iconRight={<Icon d={I.chevRight} size={13}/>} onClick={() => onJump('history')}>See all</Button>}/>
          <div className="card" style={{ overflow: 'hidden' }}>
            {status.history.slice(0, 5).map((h, i) => {
              const tone = h.status === 'success' ? 'success' : 'danger';
              return (
                <div key={i} style={{ display: 'grid', gridTemplateColumns: '20px 1fr auto', gap: 14, alignItems: 'center', padding: '11px 16px', borderBottom: i === Math.min(4, status.history.length - 1) ? 0 : '1px solid var(--s-divider)' }}>
                  <span className={`status-dot ${tone}`}/>
                  <span style={{ fontSize: 12.5, fontFamily: 'var(--s-font-mono)', color: 'var(--s-fg-2)' }}>{new Date(h.ts).toLocaleString()}</span>
                  <Badge tone={tone}>{h.status}</Badge>
                </div>
              );
            })}
          </div>
        </div>
      )}
    </div>
  );
}

// ── Operations ─────────────────────────────────────────────────────────────────
function OperationsView({ runState, logLines, summary, onRun, onStop, onClear, onResetFiles }) {
  const isRunning = runState === 'running';
  const logRef = useRef(null);
  const [tab, setTab] = useState('log');

  useEffect(() => {
    if (logRef.current) logRef.current.scrollTop = logRef.current.scrollHeight;
  }, [logLines.length]);

  return (
    <div style={{ display: 'grid', gridTemplateColumns: '1fr 320px', gap: 20, alignItems: 'start' }}>
      <div style={{ display: 'flex', flexDirection: 'column', gap: 16, minWidth: 0 }}>
        <div className="card" style={{ display: 'flex', flexDirection: 'column', minHeight: 480 }}>
          <div style={{ padding: '10px 14px', borderBottom: '1px solid var(--s-border)', display: 'flex', alignItems: 'center', gap: 14 }}>
            <Tabs value={tab} onChange={setTab} options={[
              { value: 'log', label: 'Live log', count: logLines.length },
              { value: 'summary', label: 'Summary' },
            ]}/>
            <div style={{ flex: 1 }}/>
          </div>

          {tab === 'log' ? (
            <div ref={logRef} style={{ flex: 1, overflowY: 'auto', maxHeight: 540, padding: '8px 0', fontFamily: 'var(--s-font-mono)' }}>
              {logLines.length === 0 ? (
                <div style={{ padding: 40, textAlign: 'center', color: 'var(--s-fg-3)' }}>
                  No log output. Click <strong style={{ color: 'var(--s-fg-1)' }}>Run sync now</strong> to start.
                </div>
              ) : logLines.map((l, i) => <LogLine key={i} {...l}/>)}
              {isRunning && (
                <div className="log-line dim" style={{ animation: 'pulse-opacity 1.4s infinite' }}>
                  <span className="ts">{new Date().toLocaleTimeString('en-GB')}</span>
                  <span className="lvl">…</span>
                  <span className="msg">streaming…</span>
                </div>
              )}
            </div>
          ) : (
            <div style={{ padding: 18, fontSize: 13 }}>
              {summary?.raw
                ? <pre style={{ fontFamily: 'var(--s-font-mono)', fontSize: 12, lineHeight: 1.7, whiteSpace: 'pre-wrap', color: 'var(--s-fg-1)' }}>{summary.raw}</pre>
                : <div style={{ color: 'var(--s-fg-3)' }}>No summary yet — run a sync first.</div>
              }
            </div>
          )}
        </div>
      </div>

      <div style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>
        <div className="card" style={{ padding: 16 }}>
          <div className="micro" style={{ marginBottom: 10 }}>Run</div>
          <h3 style={{ fontSize: 14, fontWeight: 600, marginBottom: 4 }}>Manual sync</h3>
          <p style={{ fontSize: 12.5, color: 'var(--s-fg-3)', marginBottom: 14, lineHeight: 1.5 }}>
            Triggers an incremental run via <code style={{ fontSize: 11.5 }}>/recents</code>. First run does a full backup.
          </p>
          {isRunning
            ? <Button full variant="secondary" destructive icon={<Icon d={I.stop} size={12}/>} onClick={onStop}>Stop sync</Button>
            : <Button full variant="primary" icon={<Icon d={I.play} size={12}/>} onClick={onRun}>Run sync now</Button>
          }
        </div>

        <div className="card" style={{ padding: 16, borderColor: 'var(--s-danger-weak)' }}>
          <div className="micro" style={{ marginBottom: 10, color: 'var(--s-danger)' }}>Danger zone</div>
          <DangerRow title="Force full file resync" desc="Resets file_sync_state. Next run sweeps all files." cta="Reset" onConfirm={onResetFiles}/>
          <div className="divider" style={{ margin: '14px 0' }}/>
          <DangerRow title="Clear database" desc="Drops all *_history tables and resets sync state. Recoverable only via pg_dump." cta="Clear" destructive onConfirm={onClear}/>
        </div>
      </div>
    </div>
  );
}

function DangerRow({ title, desc, cta, destructive, onConfirm }) {
  const [confirming, setConfirming] = useState(false);
  return (
    <div>
      <div style={{ fontSize: 13, fontWeight: 500, marginBottom: 4 }}>{title}</div>
      <p style={{ fontSize: 12, color: 'var(--s-fg-3)', marginBottom: 10, lineHeight: 1.5 }}>{desc}</p>
      {confirming ? (
        <div style={{ display: 'flex', gap: 6 }}>
          <Button size="sm" variant="secondary" onClick={() => setConfirming(false)}>Cancel</Button>
          <Button size="sm" variant={destructive ? 'danger' : 'secondary'} destructive={!destructive} onClick={() => { onConfirm(); setConfirming(false); }}>Yes, {cta.toLowerCase()}</Button>
        </div>
      ) : (
        <Button size="sm" variant="secondary" destructive onClick={() => setConfirming(true)}>{cta}</Button>
      )}
    </div>
  );
}

function formatAge(date) {
  const diff = Math.round((Date.now() - date) / 60000);
  if (isNaN(diff) || diff < 0) return '—';
  if (diff < 1) return 'just now';
  if (diff < 60) return `${diff}m ago`;
  if (diff < 1440) return `${Math.floor(diff / 60)}h ago`;
  return date.toLocaleDateString();
}

window.OverviewView = OverviewView;
window.OperationsView = OperationsView;
window.LogLine = LogLine;
