import React, { useEffect, useMemo, useState } from 'react';
import { CartesianGrid, Line, LineChart, ResponsiveContainer, Tooltip, XAxis, YAxis } from 'recharts';
import DecisionGraph from './DecisionGraph';

const API_URL = (() => {
  // Prefer explicit override via ?api=... query param or env var
  const q = new URLSearchParams(window.location.search);
  const override = q.get('api');
  if (override) return override.replace(/\/$/, '') + '/api/state';
  // If the dashboard is served from an HF Space, connect to the same origin
  if (window.location.hostname.endsWith('.hf.space')) {
    return window.location.origin + '/api/state';
  }
  return 'http://localhost:5000/api/state';
})();

function normalizeRecentActions(actions = []) {
  return actions
    .map((action, index) => {
      if (typeof action === 'string') {
        return {
          id: `${index}-${action}`,
          label: action,
          level: 'R2',
          step: index + 1,
        };
      }

      return {
        id: `${index}-${action.action || action.action_id || 'action'}`,
        label: action.action || action.action_id || 'unknown_action',
        level: action.reversibility || action.level || `R${action.r_level ?? action.actual_r_level ?? 2}`,
        step: action.step ?? index + 1,
      };
    })
    .reverse();
}

function normalizeCatastropheSeries(raw = []) {
  if (!Array.isArray(raw)) {
    return [];
  }
  return raw.map((point, index) => {
    if (typeof point === 'number') {
      return { step: index + 1, catastrophe_rate: point };
    }
    if (typeof point === 'object' && point !== null) {
      return {
        step: point.step ?? index + 1,
        catastrophe_rate: point.catastrophe_rate ?? point.value ?? 0,
      };
    }
    return { step: index + 1, catastrophe_rate: 0 };
  });
}

function normalizeLockedActions(rawLockedActions = {}) {
  if (Array.isArray(rawLockedActions)) {
    return Object.fromEntries(rawLockedActions.map((actionId) => [actionId, 'Locked by prior irreversible action']));
  }

  if (rawLockedActions && typeof rawLockedActions === 'object') {
    return rawLockedActions;
  }

  return {};
}

function normalizeThinking(rawThinking) {
  if (Array.isArray(rawThinking)) {
    return rawThinking.map((entry) => String(entry)).filter(Boolean);
  }

  if (typeof rawThinking === 'string') {
    return rawThinking
      .split(/\r?\n+/)
      .map((line) => line.trim())
      .filter(Boolean);
  }

  if (rawThinking && typeof rawThinking === 'object') {
    const values = Object.values(rawThinking)
      .flatMap((value) => (Array.isArray(value) ? value : [value]))
      .map((value) => String(value).trim())
      .filter(Boolean);
    return values;
  }

  return [];
}

function clamp(value, min, max) {
  return Math.min(max, Math.max(min, value));
}

function TrustGauge({ catastropheSeries, lockedCount, recentThinking }) {
  const latestCatastrophe = catastropheSeries.length ? catastropheSeries[catastropheSeries.length - 1].catastrophe_rate : 0;
  const trustValue = clamp(Math.round(100 - latestCatastrophe * 72 - lockedCount * 1.7), 0, 100);
  const flash = latestCatastrophe > 0.35 || lockedCount > 6;
  const warning = trustValue < 55;

  return (
    <section className={`panel trust-panel ${flash ? 'trust-flash' : ''}`}>
      <div className="card-header trust-header">
        <div>
          <h2>Board Trust</h2>
          <p>Live reputation pressure from catastrophe spikes and action lockout.</p>
        </div>
        <div className={`trust-readout ${warning ? 'warning' : 'stable'}`}>
          <span>{trustValue}</span>
          <small>/ 100</small>
        </div>
      </div>

      <div className="gauge-shell" aria-label="Board Trust gauge">
        <div className="gauge-track">
          <div className="gauge-fill" style={{ width: `${trustValue}%` }} />
        </div>
        <div className="gauge-meta">
          <span>Confidence</span>
          <strong>{flash ? 'ALERT' : warning ? 'UNDER PRESSURE' : 'STABLE'}</strong>
        </div>
      </div>

      <div className="ticker-note">
        <span className="ticker-label">Reasoning signal</span>
        <p>{recentThinking.length ? recentThinking[0] : 'Awaiting raw_thinking from the training loop...'}</p>
      </div>
    </section>
  );
}

function ReasoningTicker({ rawThinkingLines }) {
  return (
    <section className="panel ticker-panel">
      <div className="card-header ticker-header">
        <div>
          <h2>Reasoning Ticker</h2>
          <p>Streaming raw_thinking text from the live training process.</p>
        </div>
        <div className="pulse-chip terminal-chip">LIVE</div>
      </div>

      <div className="terminal-window" role="log" aria-live="polite" aria-label="Reasoning ticker window">
        <div className="terminal-scanline" />
        {rawThinkingLines.length ? (
          rawThinkingLines.map((line, index) => (
            <div className="terminal-line" key={`${index}-${line}`}>
              <span className="terminal-prompt">&gt;</span>
              <span>{line}</span>
            </div>
          ))
        ) : (
          <div className="terminal-line muted">
            <span className="terminal-prompt">&gt;</span>
            <span>Waiting for raw_thinking telemetry...</span>
          </div>
        )}
      </div>
    </section>
  );
}

function FlashRow({ item }) {
  const danger = item.level === 'R4' || item.level === 'R5';
  const className = danger ? 'flash-row danger' : 'flash-row safe';

  return (
    <div className={className}>
      <div className="flash-row-top">
        <span className="flash-step">Step {item.step}</span>
        <span className="flash-level">{item.level}</span>
      </div>
      <div className="flash-label">{item.label}</div>
    </div>
  );
}

export default function App() {
  const [state, setState] = useState({
    recent_actions: [],
    locked_actions: {},
    critical_options: {},
    catastrophe_rate: [],
    raw_thinking: [],
  });
  const [connected, setConnected] = useState(false);
  const [lastUpdated, setLastUpdated] = useState(null);

  useEffect(() => {
    let mounted = true;

    const fetchState = async () => {
      try {
        const response = await fetch(API_URL, { cache: 'no-store' });
        if (!response.ok) {
          throw new Error(`HTTP ${response.status}`);
        }
        const data = await response.json();
        if (mounted) {
          setState(data);
          setConnected(true);
          setLastUpdated(new Date());
        }
      } catch (error) {
        if (mounted) {
          setConnected(false);
        }
      }
    };

    fetchState();
    const interval = window.setInterval(fetchState, 1000);
    return () => {
      mounted = false;
      window.clearInterval(interval);
    };
  }, []);

  const lockedActions = useMemo(() => normalizeLockedActions(state.locked_actions || {}), [state.locked_actions]);
  const recentActions = useMemo(() => normalizeRecentActions(state.recent_actions || []), [state.recent_actions]);
  const catastropheSeries = useMemo(() => normalizeCatastropheSeries(state.catastrophe_rate || []), [state.catastrophe_rate]);
  const rawThinkingLines = useMemo(() => normalizeThinking(state.raw_thinking || state.thinking || state.reasoning || []), [state.raw_thinking, state.thinking, state.reasoning]);

  const lockedCount = Object.keys(lockedActions).length;
  const criticalCount = Object.values(state.critical_options || {}).filter(Boolean).length;

  return (
    <div className="app-shell">
      <div className="background-orb orb-one" />
      <div className="background-orb orb-two" />

      <header className="hero-bar">
        <div>
          <p className="eyebrow">PermanenceEnv Command Center</p>
          <h1>Live Decision Physics</h1>
          <p className="hero-copy">
            Tracking irreversible choices, option lockout, and catastrophe decay in real time.
          </p>
        </div>
        <div className={`status-pill ${connected ? 'online' : 'offline'}`}>
          <span className="status-dot" />
          {connected ? 'Connected' : 'Offline'}
        </div>
      </header>

      <main className="mission-grid">
        <aside className="left-rail">
          <ReasoningTicker rawThinkingLines={rawThinkingLines} />
          <TrustGauge catastropheSeries={catastropheSeries} lockedCount={lockedCount} recentThinking={rawThinkingLines} />
        </aside>

        <section className="center-rail">
          <DecisionGraph lockedActions={lockedActions} recentActions={recentActions} />

          <section className="panel chart-panel">
            <div className="card-header">
              <div>
                <h2>Catastrophe Rate</h2>
                <p>Desired slope: downward as the policy learns permanence.</p>
              </div>
              <div className="metric-group">
                <div className="metric">
                  <span className="metric-label">Locked</span>
                  <strong>{lockedCount}</strong>
                </div>
                <div className="metric">
                  <span className="metric-label">Critical</span>
                  <strong>{criticalCount}</strong>
                </div>
              </div>
            </div>

            <div className="chart-frame">
              <ResponsiveContainer width="100%" height={280}>
                <LineChart data={catastropheSeries}>
                  <defs>
                    <linearGradient id="catastropheStroke" x1="0" y1="0" x2="1" y2="0">
                      <stop offset="0%" stopColor="#ff4d6d" />
                      <stop offset="100%" stopColor="#ffd166" />
                    </linearGradient>
                  </defs>
                  <CartesianGrid stroke="rgba(148, 163, 184, 0.12)" strokeDasharray="4 6" />
                  <XAxis dataKey="step" stroke="#8b97b4" tick={{ fill: '#8b97b4', fontSize: 12 }} />
                  <YAxis stroke="#8b97b4" tick={{ fill: '#8b97b4', fontSize: 12 }} domain={[0, 1]} />
                  <Tooltip
                    contentStyle={{
                      background: 'rgba(8, 12, 22, 0.92)',
                      border: '1px solid rgba(148, 163, 184, 0.2)',
                      borderRadius: '14px',
                      color: '#ecf2ff',
                      boxShadow: '0 20px 40px rgba(0,0,0,0.35)',
                    }}
                    labelStyle={{ color: '#f8fafc' }}
                  />
                  <Line
                    type="monotone"
                    dataKey="catastrophe_rate"
                    stroke="url(#catastropheStroke)"
                    strokeWidth={3}
                    dot={false}
                    activeDot={{ r: 5, stroke: '#ffffff', strokeWidth: 2 }}
                  />
                </LineChart>
              </ResponsiveContainer>
            </div>
          </section>
        </section>

        <aside className="right-rail">
          <section className="panel feed-panel">
            <div className="card-header">
              <div>
                <h2>Recent Actions</h2>
                <p>Color-coded by predicted reversibility.</p>
              </div>
              <div className="pulse-chip">{recentActions.length} events</div>
            </div>

            <div className="feed-list">
              {recentActions.length ? (
                recentActions.map((item) => <FlashRow item={item} key={item.id} />)
              ) : (
                <div className="empty-state">Waiting for training telemetry...</div>
              )}
            </div>
          </section>

          <section className="panel feed-panel compact">
            <div className="card-header">
              <div>
                <h2>Critical Options</h2>
                <p>Live availability from the current state.</p>
              </div>
            </div>
            <div className="option-list">
              {Object.entries(state.critical_options || {}).map(([name, enabled]) => (
                <div key={name} className={`option-row ${enabled ? 'enabled' : 'disabled'}`}>
                  <span>{name}</span>
                  <strong>{enabled ? 'OPEN' : 'LOCKED'}</strong>
                </div>
              ))}
            </div>
          </section>
        </aside>
      </main>

      <footer className="footer-bar">
        <span>Last update: {lastUpdated ? lastUpdated.toLocaleTimeString() : 'never'}</span>
        <span>API: {API_URL}</span>
      </footer>
    </div>
  );
}
