import { useState, useEffect, useRef } from 'react';
import { Topbar } from '../../components/layout/Topbar';
import { RefreshCw, Play, Square, ExternalLink } from 'lucide-react';
import { usePageState } from '../../contexts';
import type { PerceptionSignal } from '../../contexts';
import { useLanguage } from '../../contexts/LanguageContext';

const TOKEN_KEY = 'auth_token';
function authHeader(): Record<string, string> {
  const t = localStorage.getItem(TOKEN_KEY);
  return t ? { Authorization: `Bearer ${t}` } : {};
}

interface Stats {
  total: number;
  high_impact: number;
  medium_impact: number;
  last_90_days: number;
}

const SOURCES = ['All', 'MIIT', 'UN-ECE', 'ISO', 'GB Comm.', 'EUR-Lex', 'IATF'];
const IMPACTS = ['All', 'High', 'Medium', 'Low'];

// Backend event → Signal
function mapEvent(e: Record<string, unknown>): PerceptionSignal {
  const impact = String(e.impact_level ?? '').toLowerCase();
  const backendStatus = String(e.status ?? '').toLowerCase();
  return {
    id: String(e.id ?? e.event_id ?? ''),
    source: String(e.source ?? ''),
    standard: String(e.standard ?? e.standard_code ?? e.regulation_id ?? ''),
    status: backendStatus === 'high' || backendStatus === 'urgent' ? 'risk'
          : backendStatus === 'medium' || backendStatus === 'draft' ? 'warn'
          : backendStatus === 'low' || backendStatus === 'final' ? 'ok'
          : 'info',
    title: String(e.title ?? ''),
    summary: String(e.summary ?? e.description ?? ''),
    date: String((e.published_at as string ?? '').slice(0, 10)),
    tags: Array.isArray(e.tags) ? e.tags.map(String) : [],
    impact: impact === 'high' ? 'High' : impact === 'medium' ? 'Medium' : 'Low',
  };
}

const MOCK_SIGNALS: PerceptionSignal[] = [
  {
    id: '1', source: 'EUR-Lex', standard: 'EU/2024/1689', status: 'risk',
    title: 'EU AI Act — High-risk AI in vehicles',
    summary: 'Article 9 mandates risk management systems for automotive AI classifying as high-risk under Annex III point 3.',
    date: '2025-11-18', tags: ['automotive', 'GDPR', 'certification'], impact: 'High',
  },
  {
    id: '2', source: 'MIIT', standard: 'Draft-2025-08', status: 'warn',
    title: 'MIIT Draft — in-vehicle AI training data',
    summary: 'Draft regulation requires OEM data provenance documentation and OTA audit trails for AI systems.',
    date: '2025-10-30', tags: ['OTA', 'data-governance', 'China'], impact: 'High',
  },
  {
    id: '3', source: 'ISO', standard: 'ISO/SAE 21434:2021/Amd1', status: 'info',
    title: 'ISO/SAE 21434 Amendment 1',
    summary: 'Amendment clarifies CSMS scope for software-only updates and vulnerability disclosure timelines.',
    date: '2025-10-05', tags: ['cybersecurity', 'CSMS', 'ISO'], impact: 'Medium',
  },
];

export function PerceptionPage() {
  const { t } = useLanguage();
  // Persistent state lives in PageStateContext — survives route changes
  const { perceptionState, setPerceptionState, perceptionAbortRef, perceptionCrawlAbortRef } = usePageState();
  const { signals, searchQuery, sourceFilter, impactFilter, selectedId, aiOutput, detailTab, crawlStatus } = perceptionState;

  // Stats and selectedFull are lightweight to re-fetch on mount
  const [stats, setStats] = useState<Stats | null>(null);
  const [streaming, setStreaming] = useState(false);
  const [crawling, setCrawling] = useState(false);
  // Full event detail — re-fetched when selected changes or page mounts with a selection
  const [selectedFull, setSelectedFull] = useState<Record<string, unknown> | null>(null);

  // Re-fetch stats every time the page mounts
  useEffect(() => {
    fetch('/api/v1/perception/stats', { headers: authHeader() })
      .then(r => r.json())
      .then(setStats)
      .catch(() => setStats({ total: 47, high_impact: 7, medium_impact: 18, last_90_days: 14 }));
  }, []);

  // Fetch signal list on first mount only (if empty), otherwise preserve context state
  useEffect(() => {
    if (signals.length > 0) return; // already loaded
    fetch('/api/v1/perception/events?limit=100', { headers: authHeader() })
      .then(r => r.json())
      .then(d => {
        if (Array.isArray(d?.events) && d.events.length > 0) {
          setPerceptionState(s => ({ ...s, signals: d.events.map(mapEvent) }));
        } else {
          setPerceptionState(s => ({ ...s, signals: MOCK_SIGNALS }));
        }
      })
      .catch(() => {
        setPerceptionState(s => ({ ...s, signals: s.signals.length > 0 ? s.signals : MOCK_SIGNALS }));
      });
  }, []); // eslint-disable-line react-hooks/exhaustive-deps

  // Re-fetch full event detail when navigating back with a selected signal
  useEffect(() => {
    if (selectedId) {
      fetch(`/api/v1/perception/events/${selectedId}`, { headers: authHeader() })
        .then(r => r.ok ? r.json() : null)
        .then(d => { if (d) setSelectedFull(d); })
        .catch(() => {});
    } else {
      setSelectedFull(null);
    }
  }, [selectedId]);

  const selected = signals.find(s => s.id === selectedId) ?? null;

  const filtered = signals.filter(s => {
    if (sourceFilter !== 'All' && s.source !== sourceFilter) return false;
    if (impactFilter !== 'All' && s.impact !== impactFilter) return false;
    if (searchQuery) {
      const q = searchQuery.toLowerCase();
      if (!s.title.toLowerCase().includes(q) && !s.summary.toLowerCase().includes(q)) return false;
    }
    return true;
  });

  function runAnalysis() {
    if (!selected) return;
    setStreaming(true);
    setPerceptionState(s => ({ ...s, aiOutput: '' }));
    const ctrl = new AbortController();
    perceptionAbortRef.current = ctrl;
    fetch(`/api/v1/perception/events/${selected.id}/analyze`, {
      method: 'POST',
      headers: authHeader(),
      signal: ctrl.signal,
    })
      .then(async res => {
        if (!res.body) {
          setPerceptionState(s => ({ ...s, aiOutput: 'No stream available.' }));
          setStreaming(false);
          return;
        }
        const reader = res.body.getReader();
        const dec = new TextDecoder();
        let buf = '';
        while (true) {
          const { done, value } = await reader.read();
          if (done) break;
          buf += dec.decode(value);
          const parts = buf.split('\n\n');
          buf = parts.pop() ?? '';
          for (const block of parts) {
            const dataLine = block.split('\n').find(l => l.startsWith('data: '));
            if (!dataLine) continue;
            const raw = dataLine.slice(6).trim();
            if (!raw || raw === '[DONE]') continue;
            try {
              const j = JSON.parse(raw);
              if (j.text) setPerceptionState(s => ({ ...s, aiOutput: s.aiOutput + j.text }));
              else if (typeof j === 'string') setPerceptionState(s => ({ ...s, aiOutput: s.aiOutput + j }));
            } catch {
              setPerceptionState(s => ({ ...s, aiOutput: s.aiOutput + raw }));
            }
          }
        }
        setStreaming(false);
      })
      .catch(e => {
        if (e.name !== 'AbortError') setPerceptionState(s => ({ ...s, aiOutput: 'Analysis failed. Check API connection.' }));
        setStreaming(false);
      });
  }

  function stopAnalysis() {
    perceptionAbortRef.current?.abort();
    setStreaming(false);
  }

  async function runCrawl() {
    setCrawling(true);
    setPerceptionState(s => ({ ...s, crawlStatus: t.signals.statusConnecting }));
    try {
      const res = await fetch('/api/v1/perception/crawl', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json', ...authHeader() },
        body: JSON.stringify({}),
      });
      if (!res.body) {
        setPerceptionState(s => ({ ...s, crawlStatus: 'No stream' }));
        setCrawling(false);
        return;
      }
      const reader = res.body.getReader();
      const dec = new TextDecoder();
      let buf = '';
      while (true) {
        const { done, value } = await reader.read();
        if (done) break;
        buf += dec.decode(value);
        const parts = buf.split('\n\n');
        buf = parts.pop() ?? '';
        for (const block of parts) {
          const eventLine = block.split('\n').find(l => l.startsWith('event: '));
          const dataLine = block.split('\n').find(l => l.startsWith('data: '));
          const evtName = eventLine?.slice(7).trim();
          const raw = dataLine?.slice(6).trim();
          if (!raw) continue;
          try {
            const d = JSON.parse(raw);
            if (evtName === 'progress') {
              setPerceptionState(s => ({
                ...s,
                crawlStatus: `${d.source}: ${d.stage === 'fetching' ? t.signals.statusCrawling : d.stage === 'processing' ? t.signals.statusProcessing.replace('{count}', String(d.fetched)) : t.signals.statusComplete.replace('{count}', String(d.new))}`,
              }));
            } else if (evtName === 'done') {
              setPerceptionState(s => ({ ...s, crawlStatus: t.signals.statusUpdateComplete.replace('{new}', String(d.total_new)).replace('{updated}', String(d.total_updated)) }));
              fetch('/api/v1/perception/events?limit=100', { headers: authHeader() })
                .then(r => r.json())
                .then(d2 => {
                  if (Array.isArray(d2?.events)) {
                    setPerceptionState(s => ({ ...s, signals: d2.events.map(mapEvent) }));
                  }
                });
            } else if (evtName === 'error') {
              setPerceptionState(s => ({
                ...s,
                crawlStatus: t.signals.statusError.replace('{message}', typeof d === 'string' ? d : String(d.message)),
              }));
            }
          } catch { /* ignore */ }
        }
      }
    } catch (e: unknown) {
      setPerceptionState(s => ({
        ...s,
        crawlStatus: t.signals.statusConnFailed.replace('{message}', e instanceof Error ? e.message : String(e)),
      }));
    }
    setCrawling(false);
  }

  function selectSignal(sig: PerceptionSignal) {
    setPerceptionState(s => ({
      ...s,
      selectedId: sig.id,
      aiOutput: '',
      detailTab: 'overview',
    }));
    setSelectedFull(null);
    setStreaming(false);
    perceptionAbortRef.current?.abort();
  }

  return (
    <div className="perception-page">
      <Topbar
        title={t.signals.topbarTitle}
        subtitle={t.signals.topbarSub}
        actions={
          <>
            <div className="search-box">
              <input
                placeholder={t.signals.searchPlaceholder}
                value={searchQuery}
                onChange={e => setPerceptionState(s => ({ ...s, searchQuery: e.target.value }))}
              />
            </div>
            <button className="btn sm primary" onClick={runCrawl} disabled={crawling}>
              <RefreshCw size={13} className={crawling ? 'spin' : ''} />
              {crawling ? t.signals.crawlingBtn : t.signals.refreshBtn}
            </button>
            {crawlStatus && (
              <span style={{ fontSize: 12, color: 'var(--text-secondary)', marginLeft: 8 }}>
                {crawlStatus}
              </span>
            )}
          </>
        }
      />

      <div className="stats-bar">
        <div className="sbar-cell">
          <span className="sbar-val">{stats?.total ?? '—'}</span>
          <span className="sbar-lbl">{t.signals.statTotal}</span>
        </div>
        <div className="sbar-cell danger">
          <span className="sbar-val">{stats?.high_impact ?? '—'}</span>
          <span className="sbar-lbl">{t.signals.statHigh}</span>
        </div>
        <div className="sbar-cell warn">
          <span className="sbar-val">{stats?.medium_impact ?? '—'}</span>
          <span className="sbar-lbl">{t.signals.statMedium}</span>
        </div>
        <div className="sbar-cell accent">
          <span className="sbar-val">{stats?.last_90_days ?? '—'}</span>
          <span className="sbar-lbl">{t.signals.statLast90}</span>
        </div>
      </div>

      <div className="filter-bar">
        <div className="chip-group">
          {SOURCES.map(s => (
            <button
              key={s}
              className={`chip${sourceFilter === s ? ' active' : ''}`}
              onClick={() => setPerceptionState(st => ({ ...st, sourceFilter: s }))}
            >
              {s}
            </button>
          ))}
        </div>
        <div className="filter-sep" />
        <div className="chip-group">
          {IMPACTS.map(i => (
            <button
              key={i}
              className={`chip${impactFilter === i ? ' active' : ''}`}
              onClick={() => setPerceptionState(st => ({ ...st, impactFilter: i }))}
            >
              {i}
            </button>
          ))}
        </div>
      </div>

      <div className="perception-split">
        <div className="feed-pane">
          {filtered.map(sig => (
            <div
              key={sig.id}
              className={`ev-card${selectedId === sig.id ? ' selected' : ''}`}
              onClick={() => selectSignal(sig)}
            >
              <div className="ev-top">
                <span className="source-tag">{sig.source}</span>
                <span className="ev-std">{sig.standard}</span>
                <span className={`status ${sig.status}`}>
                  {sig.status === 'ok' ? t.signals.badgeFinal : sig.status === 'warn' ? t.signals.badgeDraft : sig.status === 'risk' ? t.signals.badgeUrgent : t.signals.badgePublished}
                </span>
              </div>
              <div className="ev-title">{sig.title}</div>
              <div className="ev-summary">{sig.summary}</div>
              <div className="ev-bottom">
                <span className="ev-date">{sig.date}</span>
                <div className="ev-tags">{sig.tags.map(tag => <span key={tag} className="ev-tag">{tag}</span>)}</div>
                <span className={`impact-dot impact-${sig.impact.toLowerCase()}`}>{sig.impact}</span>
              </div>
            </div>
          ))}
        </div>

        <div className="analysis-pane">
          {!selected ? (
            <div className="analysis-empty">
              <div className="empty-ring" />
              <p>{t.signals.emptySelectSignal}</p>
            </div>
          ) : (
            <>
              <div className="card detail-card">
                <div className="detail-header">
                  <span className="source-tag">{selected.source}</span>
                  <span className="ev-std">{selected.standard}</span>
                  <span className={`status ${selected.status}`}>
                    {selected.status === 'risk' ? t.signals.badgeUrgent : selected.status === 'warn' ? t.signals.badgeDraft : t.signals.badgePublished}
                  </span>
                  {selectedFull?.change_summary && (
                    <span className="status warn" style={{ marginLeft: 'auto' }}>CHANGED</span>
                  )}
                </div>
                <div className="detail-title">{selected.title}</div>
                <p className="detail-summary">{selected.summary}</p>
                <div className="detail-actions">
                  {!streaming
                    ? <button className="btn sm primary" onClick={runAnalysis}><Play size={12} />{t.signals.runAnalysis}</button>
                    : <button className="btn sm" onClick={stopAnalysis}><Square size={12} />{t.signals.stopBtn}</button>
                  }
                  {selected && (
                    <a
                      href={(selectedFull?.full_text_url as string) || '#'}
                      target="_blank"
                      rel="noopener noreferrer"
                      className="btn sm"
                    >
                      <ExternalLink size={12} />{t.signals.sourceLink}
                    </a>
                  )}
                </div>
              </div>

              <div className="detail-tabs">
                {(['overview', 'obligations', 'assessment', 'diff'] as const).map(tab => (
                  <button
                    key={tab}
                    className={`detail-tab${detailTab === tab ? ' active' : ''}${tab === 'diff' && !selectedFull?.change_summary ? ' disabled' : ''}`}
                    onClick={() => {
                      if (tab !== 'diff' || selectedFull?.change_summary) {
                        setPerceptionState(s => ({ ...s, detailTab: tab }));
                      }
                    }}
                  >
                    {tab === 'overview' ? t.signals.tabOverview : tab === 'obligations' ? t.signals.tabObligations : tab === 'assessment' ? t.signals.tabImpact : t.signals.tabChanges}
                  </button>
                ))}
              </div>

              {detailTab === 'overview' && (
                <div className="card">
                  <div className="card-header">{t.signals.cardScopeHeader}</div>
                  <p className="detail-summary" style={{ marginTop: 8 }}>
                    {(selectedFull?.scope as string) || selected.summary}
                  </p>
                  {selectedFull?.penalties && (
                    <p style={{ fontSize: 13, color: 'var(--danger)', marginTop: 6 }}>
                      ⚠ {selectedFull.penalties as string}
                    </p>
                  )}
                </div>
              )}

              {detailTab === 'obligations' && (
                <div className="card">
                  <div className="card-header">{t.signals.cardObligationsHeader}</div>
                  {(() => {
                    const obs = (selectedFull?.obligations as Array<Record<string, string>>) || [];
                    const deadlines = (selectedFull?.deadlines as Array<Record<string, string>>) || [];
                    return obs.length === 0 && deadlines.length === 0 ? (
                      <p className="detail-summary" style={{ marginTop: 8 }}>{t.signals.obligationsEmpty}</p>
                    ) : (
                      <>
                        {obs.length > 0 && (
                          <table style={{ width: '100%', fontSize: 13, borderCollapse: 'collapse', marginTop: 8 }}>
                            <thead>
                              <tr style={{ borderBottom: '1px solid var(--border)' }}>
                                <th style={{ textAlign: 'left', padding: '4px 8px' }}>{t.signals.colObligationDesc}</th>
                                <th style={{ textAlign: 'left', padding: '4px 8px', width: 80 }}>{t.signals.colSubject}</th>
                                <th style={{ textAlign: 'left', padding: '4px 8px', width: 60 }}>{t.signals.colType}</th>
                              </tr>
                            </thead>
                            <tbody>
                              {obs.map((ob, i) => (
                                <tr key={i} style={{ borderBottom: '1px solid var(--border-faint)' }}>
                                  <td style={{ padding: '6px 8px' }}>{ob.text}</td>
                                  <td style={{ padding: '6px 8px', color: 'var(--text-secondary)' }}>{ob.subject}</td>
                                  <td style={{ padding: '6px 8px' }}>
                                    <span className={`status ${ob.deontic === 'must' || ob.deontic === 'shall' ? 'risk' : ob.deontic === 'prohibited' ? 'risk' : 'info'}`}>
                                      {ob.deontic}
                                    </span>
                                  </td>
                                </tr>
                              ))}
                            </tbody>
                          </table>
                        )}
                        {deadlines.length > 0 && (
                          <div style={{ marginTop: 12 }}>
                            <div className="card-header">{t.signals.colDeadline}</div>
                            {deadlines.map((d, i) => (
                              <div key={i} style={{ fontSize: 13, padding: '4px 0', display: 'flex', gap: 12 }}>
                                <span style={{ fontWeight: 600, color: 'var(--danger)' }}>{d.date || t.signals.deadlinePending}</span>
                                <span style={{ color: 'var(--text-secondary)' }}>{d.description}</span>
                              </div>
                            ))}
                          </div>
                        )}
                      </>
                    );
                  })()}
                </div>
              )}

              {detailTab === 'assessment' && (
                <div className="card docs-card">
                  <div className="card-header">{t.signals.cardAffectedDocs}</div>
                  {(() => {
                    const docs = (selectedFull?.affected_docs as Array<Record<string, unknown>>);
                    const displayDocs = docs && docs.length > 0 ? docs : [];
                    return displayDocs.length === 0
                      ? <p className="detail-summary" style={{ marginTop: 8 }}>{t.signals.noAffectedDocs}</p>
                      : displayDocs.map((d, i) => (
                          <div key={i} className="doc-row">
                            <span className="doc-score">{Math.round(Number(d.score ?? 0) * 100)}%</span>
                            <div>
                              <div className="doc-name">
                                {String(d.doc_name || '')}
                                <span className="doc-clause">{String(d.key_clauses || d.clause || '')}</span>
                              </div>
                              {d.snippet && <div className="doc-snippet">{String(d.snippet)}</div>}
                              {d.recommendation && (
                                <div style={{ fontSize: 12, color: 'var(--accent)', marginTop: 2 }}>→ {String(d.recommendation)}</div>
                              )}
                            </div>
                          </div>
                        ));
                  })()}
                </div>
              )}

              {detailTab === 'diff' && selectedFull?.change_summary && (
                <div className="card">
                  <div className="card-header">{t.signals.diffCardHeader}</div>
                  <p style={{ fontSize: 13, color: 'var(--text-secondary)', marginTop: 8 }}>
                    {selectedFull.change_summary as string}
                  </p>
                  {(() => {
                    const sections = (selectedFull.changed_sections as Array<Record<string, unknown>>) || [];
                    return sections.map((s, i) => (
                      <div key={i} style={{ marginTop: 12, borderTop: '1px solid var(--border)', paddingTop: 10 }}>
                        <div style={{ display: 'flex', gap: 8, marginBottom: 6 }}>
                          <span className={`status ${s.change_type === 'tightened' || s.change_type === 'added' ? 'risk' : s.change_type === 'removed' ? 'warn' : 'info'}`}>
                            {String(s.change_type)}
                          </span>
                          <span style={{ fontSize: 12, color: 'var(--text-secondary)' }}>cosine: {String(s.similarity)}</span>
                        </div>
                        <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 8, fontSize: 12 }}>
                          <div style={{ background: 'var(--danger-bg)', padding: 8, borderRadius: 4 }}>
                            <div style={{ fontWeight: 600, marginBottom: 4 }}>{t.signals.diffOld}</div>
                            {String(s.old_text || '')}
                          </div>
                          <div style={{ background: 'var(--success-bg)', padding: 8, borderRadius: 4 }}>
                            <div style={{ fontWeight: 600, marginBottom: 4 }}>{t.signals.diffNew}</div>
                            {String(s.new_text || '')}
                          </div>
                        </div>
                        {s.summary && <p style={{ fontSize: 12, marginTop: 6, color: 'var(--text-secondary)' }}>{String(s.summary)}</p>}
                      </div>
                    ));
                  })()}
                </div>
              )}

              {(aiOutput || streaming) && (
                <div className="card ai-card">
                  <div className="card-header">{t.signals.cardAIImpact}</div>
                  <div className="ai-output">
                    {aiOutput}
                    {streaming && <span className="blink-cursor">▋</span>}
                  </div>
                </div>
              )}
            </>
          )}
        </div>
      </div>

      <footer className="page-footer">
        <div className="live-dot" />
        <span>{t.signals.footerText}</span>
      </footer>
    </div>
  );
}
