import { useState, useEffect } from 'react';
import { useParams, useNavigate, useSearchParams, Link } from 'react-router-dom';
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import { ChevronRight, Archive, Pin, ExternalLink, Play, Pencil, Save, X, RefreshCw, BarChart2 } from 'lucide-react';
import { experimentsApi, backtestApi, runsApi, sqsApi } from '../api/client';
import type { SqsResult } from '../api/client';
import { Loading, ErrorState } from '../components/common/Loading';
import { StatusBadge } from '../components/common/StatusBadge';
import { fmt, fmtPct, fmtDate } from '../lib/utils';
import { LineageTree } from '../components/experiments/LineageTree';

type Tab = 'overview' | 'engines' | 'tree' | 'runs' | 'raw';

interface SleeveInfo { label: string; value: string; color: string }

const inputStyle: React.CSSProperties = {
  width: '100%', padding: '8px 12px', fontSize: 14,
  fontFamily: 'var(--font-mono)', background: 'var(--bg2)',
  border: '1px solid var(--border-md)', borderRadius: 7,
  color: 'var(--text1)', outline: 'none', boxSizing: 'border-box',
};

function extractBakedSleeves(config: any): SleeveInfo[] {
  const overrides = config?.overrides ?? {};
  const sleeves: SleeveInfo[] = [];
  const parking = overrides?.risk?.cash_parking_preset;
  if (parking) sleeves.push({ label: 'parking', value: parking, color: 'var(--orange)' });
  const idle = overrides?.idle_alpha_sleeve_preset;
  if (idle) sleeves.push({ label: 'idle_alpha', value: idle, color: 'var(--green)' });
  const form4 = overrides?.form4_capture_sleeve_preset;
  if (form4) sleeves.push({ label: 'form4', value: form4, color: 'var(--cyan)' });
  const ownership = overrides?.ownership_capture_sleeve_preset;
  if (ownership) sleeves.push({ label: 'ownership', value: ownership, color: 'var(--violet, var(--cyan))' });
  const riskOff = overrides?.risk_off_alpha_sleeve_preset;
  if (riskOff) sleeves.push({ label: 'risk_off', value: riskOff, color: 'var(--red)' });
  return sleeves;
}

function SleeveBadge({ label, value, color }: SleeveInfo) {
  return (
    <div style={{
      display: 'flex', flexDirection: 'column', gap: 2,
      background: `color-mix(in srgb, ${color} 10%, transparent)`,
      border: `1px solid color-mix(in srgb, ${color} 28%, transparent)`,
      borderRadius: 8, padding: '8px 14px',
    }}>
      <span style={{ fontFamily: 'var(--font-mono)', fontSize: 10, letterSpacing: '0.10em', textTransform: 'uppercase', color: `color-mix(in srgb, ${color} 70%, var(--text3))` }}>
        {label}
      </span>
      <span style={{ fontFamily: 'var(--font-mono)', fontSize: 13, fontWeight: 600, color }}>
        {value}
      </span>
    </div>
  );
}

function MetricCard({ label, value, color = 'var(--text1)', sub }: { label: string; value: string; color?: string; sub?: string }) {
  return (
    <div style={{ background: 'var(--bg2)', border: '1px solid var(--border)', borderRadius: 10, padding: '14px 16px' }}>
      <div style={{ fontFamily: 'var(--font-mono)', fontSize: 11, letterSpacing: '0.10em', textTransform: 'uppercase', color: 'var(--text3)', marginBottom: 8 }}>
        {label}
      </div>
      <div style={{ fontFamily: 'var(--font-mono)', fontSize: 28, fontWeight: 700, color }}>
        {value}
      </div>
      {sub && <div style={{ fontSize: 12, color: 'var(--text3)', marginTop: 3 }}>{sub}</div>}
    </div>
  );
}

// Sleeve select dropdown (reuses ComposeStrategy pattern)
function SleeveSelect({
  label, color, value, onChange, presetsData,
}: {
  label: string; color: string; value: string;
  onChange: (v: string) => void;
  presetsData?: { presets: string[]; groups: Record<string, string[]> };
}) {
  return (
    <div>
      <label style={{ display: 'block', fontFamily: 'var(--font-mono)', fontSize: 11, letterSpacing: '0.08em', textTransform: 'uppercase', color: 'var(--text3)', marginBottom: 5 }}>
        {label}
      </label>
      <select
        value={value}
        onChange={e => onChange(e.target.value)}
        style={{ ...inputStyle, fontSize: 13, color: value ? color : 'var(--text3)' }}
      >
        <option value="">— none —</option>
        {presetsData ? Object.entries(presetsData.groups).map(([group, names]) => (
          <optgroup key={group} label={group}>
            {names.map(n => <option key={n} value={n}>{n}</option>)}
          </optgroup>
        )) : null}
      </select>
    </div>
  );
}

// Numeric override input
function NumericField({ label, value, onChange }: { label: string; value: number | undefined; onChange: (v: number | null) => void }) {
  if (value === undefined) return null;
  return (
    <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
      <span style={{ fontFamily: 'var(--font-mono)', fontSize: 12, color: 'var(--text3)', minWidth: 200, flexShrink: 0 }}>{label}</span>
      <input
        type="number"
        value={value ?? ''}
        onChange={e => onChange(e.target.value === '' ? null : Number(e.target.value))}
        style={{ ...inputStyle, width: 120, padding: '5px 9px', fontSize: 13 }}
        step="any"
      />
    </div>
  );
}

function ScoreBar({ value, max = 100 }: { value: number | null; max?: number }) {
  if (value == null) return <span style={{ color: 'var(--text3)', fontFamily: 'var(--font-mono)', fontSize: 12 }}>—</span>;
  const pct = Math.max(0, Math.min(100, (value / max) * 100));
  const color = value >= 70 ? 'var(--green)' : value >= 40 ? 'var(--gold)' : 'var(--red)';
  return (
    <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
      <div style={{ flex: 1, height: 6, background: 'var(--bg2)', borderRadius: 3, overflow: 'hidden' }}>
        <div style={{ width: `${pct}%`, height: '100%', background: color, borderRadius: 3, transition: 'width 0.4s ease' }} />
      </div>
      <span style={{ fontFamily: 'var(--font-mono)', fontSize: 13, fontWeight: 600, color, minWidth: 38, textAlign: 'right' }}>
        {value.toFixed(1)}
      </span>
    </div>
  );
}

function SqsPanel({ result, isLoading, isRescoring, isPipelining, pipelineStep, onCompute, onRescore, onPipeline, hasJournalEntry, experimentName }: {
  result: SqsResult | null;
  isLoading: boolean;
  isRescoring: boolean;
  isPipelining: boolean;
  pipelineStep: string;
  onCompute: () => void;
  onRescore: () => void;
  onPipeline: () => void;
  hasJournalEntry: boolean;
  experimentName: string;
}) {
  const busy = isLoading || isRescoring || isPipelining;

  return (
    <div style={{
      background: 'var(--bg1)', border: '1px solid var(--border)', borderRadius: 12,
      padding: '18px 20px', boxShadow: '0 1px 3px rgba(0,0,0,0.04)',
    }}>
      {/* Header */}
      <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 16 }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
          <BarChart2 size={15} style={{ color: 'var(--gold)' }} />
          <span style={{ fontFamily: 'var(--font-mono)', fontSize: 12, letterSpacing: '0.10em', textTransform: 'uppercase', color: 'var(--text3)' }}>
            SQS v9 Breakdown
          </span>
        </div>
        <div style={{ display: 'flex', gap: 6 }}>
          {hasJournalEntry ? (
            <>
              <button
                onClick={onCompute}
                disabled={busy}
                title="Compute live (read-only)"
                style={{
                  display: 'flex', alignItems: 'center', gap: 5, padding: '5px 10px',
                  fontSize: 12, fontWeight: 500, borderRadius: 6,
                  background: 'color-mix(in srgb, var(--cyan) 8%, transparent)',
                  border: '1px solid color-mix(in srgb, var(--cyan) 20%, transparent)',
                  color: busy ? 'var(--text3)' : 'var(--cyan)',
                  cursor: busy ? 'not-allowed' : 'pointer',
                  opacity: busy ? 0.5 : 1,
                }}
              >
                {isLoading ? <RefreshCw size={11} className="spin" /> : <BarChart2 size={11} />}
                {isLoading ? 'Computing…' : 'Compute'}
              </button>
              <button
                onClick={onRescore}
                disabled={busy}
                title="Rescore and save to journal"
                style={{
                  display: 'flex', alignItems: 'center', gap: 5, padding: '5px 10px',
                  fontSize: 12, fontWeight: 500, borderRadius: 6,
                  background: 'color-mix(in srgb, var(--gold) 8%, transparent)',
                  border: '1px solid color-mix(in srgb, var(--gold) 20%, transparent)',
                  color: busy ? 'var(--text3)' : 'var(--gold)',
                  cursor: busy ? 'not-allowed' : 'pointer',
                  opacity: busy ? 0.5 : 1,
                }}
              >
                {isRescoring ? <RefreshCw size={11} className="spin" /> : <RefreshCw size={11} />}
                {isRescoring ? 'Rescoring…' : 'Rescore & Save'}
              </button>
            </>
          ) : (
            <button
              onClick={onPipeline}
              disabled={busy}
              title="Scan existing backtest runs, record to journal, and compute SQS"
              style={{
                display: 'flex', alignItems: 'center', gap: 5, padding: '5px 10px',
                fontSize: 12, fontWeight: 500, borderRadius: 6,
                background: 'color-mix(in srgb, var(--cyan) 8%, transparent)',
                border: '1px solid color-mix(in srgb, var(--cyan) 20%, transparent)',
                color: busy ? 'var(--text3)' : 'var(--cyan)',
                cursor: busy ? 'not-allowed' : 'pointer',
                opacity: busy ? 0.5 : 1,
              }}
            >
              {isPipelining ? <RefreshCw size={11} className="spin" /> : <BarChart2 size={11} />}
              {isPipelining ? 'Recording…' : 'Record & Compute'}
            </button>
          )}
        </div>
      </div>

      {/* Progress / Loading state */}
      {busy && (
        <div style={{
          display: 'flex', flexDirection: 'column', gap: 6,
          padding: '14px 0', alignItems: 'center',
        }}>
          <div style={{ display: 'flex', gap: 6, alignItems: 'center' }}>
            <RefreshCw size={14} className="spin" style={{ color: 'var(--cyan)' }} />
            <span style={{ fontFamily: 'var(--font-mono)', fontSize: 13, color: 'var(--text2)' }}>
              {isRescoring ? 'Computing SQS v9, saving to journal, rebuilding leaderboard…'
                : isPipelining ? (pipelineStep || 'Running backtest pipeline…')
                : 'Computing SQS v9…'}
            </span>
          </div>
          <div style={{ width: '100%', height: 3, background: 'var(--bg2)', borderRadius: 2, overflow: 'hidden' }}>
            <div style={{
              height: '100%', borderRadius: 2,
              background: 'linear-gradient(90deg, var(--cyan), var(--gold))',
              animation: 'indeterminate 1.4s ease infinite',
              width: '40%',
            }} />
          </div>
        </div>
      )}

      {/* No result yet */}
      {!busy && !result && (
        <div style={{ padding: '20px 0', textAlign: 'center', color: 'var(--text3)', fontFamily: 'var(--font-mono)', fontSize: 13 }}>
          {hasJournalEntry
            ? 'Click Compute to see SQS v9 breakdown'
            : 'Click Record & Compute to scan backtest runs and compute SQS'}
        </div>
      )}

      {/* Pipeline: no runs found */}
      {!busy && result && (result as any).pipeline_status === 'no_runs' && (
        <div style={{
          padding: '12px 14px', borderRadius: 8, fontSize: 13, fontFamily: 'var(--font-mono)',
          background: 'color-mix(in srgb, var(--text3) 8%, transparent)',
          border: '1px solid color-mix(in srgb, var(--text3) 20%, transparent)',
          color: 'var(--text2)',
        }}>
          No backtest runs found for <b>{experimentName}</b>. Run a backtest first (use the Backtest page), then click Record & Compute.
        </div>
      )}

      {/* Result */}
      {!busy && result && (result as any).pipeline_status !== 'no_runs' && (
        <div style={{ display: 'flex', flexDirection: 'column', gap: 14 }}>
          {/* Pending */}
          {result.sqs_score == null && result.pending_reason && (
            <div style={{
              padding: '8px 12px', borderRadius: 7, fontSize: 13, fontFamily: 'var(--font-mono)',
              background: result.pending_reason === 'no journal entry'
                ? 'color-mix(in srgb, var(--text3) 8%, transparent)'
                : 'color-mix(in srgb, var(--gold) 8%, transparent)',
              border: `1px solid ${result.pending_reason === 'no journal entry'
                ? 'color-mix(in srgb, var(--text3) 20%, transparent)'
                : 'color-mix(in srgb, var(--gold) 20%, transparent)'}`,
              color: result.pending_reason === 'no journal entry' ? 'var(--text3)' : 'var(--gold)',
            }}>
              {result.pending_reason === 'no journal entry'
                ? '— No journal entry for this experiment'
                : `⏳ PENDING — waiting for: ${result.pending_reason}`}
            </div>
          )}

          {/* 3-pillar grid */}
          <div>
            <div style={{ fontFamily: 'var(--font-mono)', fontSize: 11, letterSpacing: '0.08em', textTransform: 'uppercase', color: 'var(--text3)', marginBottom: 10 }}>
              3-Pillar Core
            </div>
            <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
              {[
                { label: 'RQS', weight: '35%', value: result.pillars.rqs_score, color: 'var(--cyan)' },
                { label: 'WFQS v2', weight: '40%', value: result.pillars.wfqs_v2_score, color: 'var(--green)' },
                { label: `Regime (${result.pillars.regime_source})`, weight: '25%', value: result.pillars.regime_score, color: 'var(--orange)' },
              ].map(({ label, weight, value, color }) => (
                <div key={label} style={{ display: 'grid', gridTemplateColumns: '140px 1fr', gap: 10, alignItems: 'center' }}>
                  <div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
                    <span style={{ fontFamily: 'var(--font-mono)', fontSize: 13, color: 'var(--text2)' }}>{label}</span>
                    <span style={{ fontFamily: 'var(--font-mono)', fontSize: 10, color: 'var(--text3)' }}>{weight}</span>
                  </div>
                  <div style={{ position: 'relative' }}>
                    <div style={{ flex: 1, height: 6, background: 'var(--bg2)', borderRadius: 3, overflow: 'hidden' }}>
                      <div style={{
                        width: `${Math.max(0, Math.min(100, ((value ?? 0) / 100) * 100))}%`,
                        height: '100%', background: color, borderRadius: 3, transition: 'width 0.4s ease',
                      }} />
                    </div>
                    <div style={{ display: 'flex', justifyContent: 'space-between', marginTop: 2 }}>
                      <span style={{ fontFamily: 'var(--font-mono)', fontSize: 11, color: 'var(--text3)' }}>0</span>
                      <span style={{ fontFamily: 'var(--font-mono)', fontSize: 12, fontWeight: 600, color }}>
                        {value != null ? value.toFixed(1) : '—'}
                      </span>
                      <span style={{ fontFamily: 'var(--font-mono)', fontSize: 11, color: 'var(--text3)' }}>100</span>
                    </div>
                  </div>
                </div>
              ))}
            </div>
          </div>

          {/* Core + Gates */}
          <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 10 }}>
            <div style={{ background: 'var(--bg2)', borderRadius: 8, padding: '10px 14px' }}>
              <div style={{ fontFamily: 'var(--font-mono)', fontSize: 11, textTransform: 'uppercase', letterSpacing: '0.08em', color: 'var(--text3)', marginBottom: 6 }}>Core</div>
              <ScoreBar value={result.pillars.core_score} />
            </div>
            <div style={{ background: 'var(--bg2)', borderRadius: 8, padding: '10px 14px' }}>
              <div style={{ fontFamily: 'var(--font-mono)', fontSize: 11, textTransform: 'uppercase', letterSpacing: '0.08em', color: 'var(--text3)', marginBottom: 6 }}>Gates</div>
              <div style={{ display: 'flex', gap: 10, fontFamily: 'var(--font-mono)', fontSize: 12 }}>
                {[
                  { label: 'Deploy', value: result.gates.deployment_gate_factor },
                  { label: 'RB', value: result.gates.robustness_gate_factor },
                  { label: 'Activity', value: result.gates.activity_factor },
                ].map(({ label, value }) => (
                  <div key={label} style={{ flex: 1, textAlign: 'center' }}>
                    <div style={{ color: 'var(--text3)', fontSize: 10, marginBottom: 2 }}>{label}</div>
                    <div style={{ color: value != null && value < 0.9 ? 'var(--red)' : 'var(--text1)', fontWeight: 600 }}>
                      {value != null ? value.toFixed(2) : '—'}
                    </div>
                  </div>
                ))}
              </div>
            </div>
          </div>

          {/* Final SQS */}
          <div style={{
            display: 'flex', alignItems: 'center', justifyContent: 'space-between',
            padding: '12px 16px', borderRadius: 9,
            background: result.sqs_score != null
              ? 'color-mix(in srgb, var(--gold) 8%, transparent)'
              : 'var(--bg2)',
            border: `1px solid ${result.sqs_score != null ? 'color-mix(in srgb, var(--gold) 22%, transparent)' : 'var(--border)'}`,
          }}>
            <div>
              <div style={{ fontFamily: 'var(--font-mono)', fontSize: 11, textTransform: 'uppercase', letterSpacing: '0.08em', color: 'var(--text3)', marginBottom: 4 }}>SQS v9</div>
              <div style={{ fontFamily: 'var(--font-mono)', fontSize: 28, fontWeight: 700, color: 'var(--gold)' }}>
                {result.sqs_score != null ? result.sqs_score.toFixed(1) : '—'}
              </div>
              {result.source && (
                <div style={{ fontFamily: 'var(--font-mono)', fontSize: 10, color: 'var(--text3)', marginTop: 2 }}>{result.source}</div>
              )}
            </div>
            {result.stored_sqs_score != null && result.sqs_score != null && (
              <div style={{ textAlign: 'right' }}>
                <div style={{ fontFamily: 'var(--font-mono)', fontSize: 11, color: 'var(--text3)', marginBottom: 3 }}>stored</div>
                <div style={{ fontFamily: 'var(--font-mono)', fontSize: 18, color: 'var(--text2)' }}>
                  {result.stored_sqs_score.toFixed(1)}
                </div>
                {Math.abs(result.sqs_score - result.stored_sqs_score) > 0.05 && (
                  <div style={{
                    fontFamily: 'var(--font-mono)', fontSize: 12, fontWeight: 600,
                    color: result.sqs_score > result.stored_sqs_score ? 'var(--green)' : 'var(--red)',
                  }}>
                    {result.sqs_score > result.stored_sqs_score ? '+' : ''}{(result.sqs_score - result.stored_sqs_score).toFixed(1)}
                  </div>
                )}
              </div>
            )}
          </div>

          {/* Aux scores */}
          {(result.scenario_robustness_score != null || result.overfit_check_score != null) && (
            <div style={{ display: 'flex', gap: 10 }}>
              {result.scenario_robustness_score != null && (
                <div style={{ flex: 1, background: 'var(--bg2)', borderRadius: 8, padding: '8px 12px' }}>
                  <div style={{ fontFamily: 'var(--font-mono)', fontSize: 10, textTransform: 'uppercase', letterSpacing: '0.08em', color: 'var(--text3)', marginBottom: 4 }}>Scenario RRS</div>
                  <ScoreBar value={result.scenario_robustness_score} />
                </div>
              )}
              {result.overfit_check_score != null && (
                <div style={{ flex: 1, background: 'var(--bg2)', borderRadius: 8, padding: '8px 12px' }}>
                  <div style={{ fontFamily: 'var(--font-mono)', fontSize: 10, textTransform: 'uppercase', letterSpacing: '0.08em', color: 'var(--text3)', marginBottom: 4 }}>Overfit Check</div>
                  <ScoreBar value={result.overfit_check_score} />
                </div>
              )}
            </div>
          )}

          {/* Rescore note */}
          {result.entries_updated != null && (
            <div style={{ fontFamily: 'var(--font-mono)', fontSize: 11, color: 'var(--green)', textAlign: 'right' }}>
              ✓ Saved to journal · leaderboard rebuilt
            </div>
          )}
        </div>
      )}
    </div>
  );
}

export function ExperimentDetailPage() {
  const { name } = useParams<{ name: string }>();
  const navigate = useNavigate();
  const [searchParams] = useSearchParams();
  const qc = useQueryClient();
  const [tab, setTab] = useState<Tab>('overview');
  const [sqsResult, setSqsResult] = useState<SqsResult | null>(null);

  // Edit mode state
  const [editing, setEditing] = useState(false);
  const [draft, setDraft] = useState<any>(null);
  const [rawJsonText, setRawJsonText] = useState('');
  const [rawJsonError, setRawJsonError] = useState<string | null>(null);
  const [tagInput, setTagInput] = useState('');

  const expName = decodeURIComponent(name ?? '');

  const { data: config, isLoading, error } = useQuery({
    queryKey: ['experiment', expName],
    queryFn: () => experimentsApi.get(expName),
    enabled: !!expName,
  });

  const { data: runs } = useQuery({
    queryKey: ['runs', expName],
    queryFn: () => runsApi.list({ experiment: expName, limit: 30 }),
    enabled: tab === 'runs' && !!expName,
  });

  const { data: lineage } = useQuery({
    queryKey: ['lineage', expName],
    queryFn: () => experimentsApi.lineage(expName),
    enabled: !!expName,
  });

  // Sleeve preset queries (only fetch when editing)
  const { data: parkingPresetsData } = useQuery({
    queryKey: ['parking-presets'],
    queryFn: () => backtestApi.parkingPresets(),
    enabled: editing, staleTime: 60_000,
  });
  const { data: idleAlphaPresetsData } = useQuery({
    queryKey: ['idle-alpha-presets'],
    queryFn: () => backtestApi.idleAlphaPresets(),
    enabled: editing, staleTime: 60_000,
  });
  const { data: form4PresetsData } = useQuery({
    queryKey: ['form4-capture-presets'],
    queryFn: () => backtestApi.form4CapturePresets(),
    enabled: editing, staleTime: 60_000,
  });
  const { data: ownershipPresetsData } = useQuery({
    queryKey: ['ownership-capture-presets'],
    queryFn: () => backtestApi.ownershipCapturePresets(),
    enabled: editing, staleTime: 60_000,
  });
  const { data: riskOffPresetsData } = useQuery({
    queryKey: ['risk-off-alpha-presets'],
    queryFn: () => backtestApi.riskOffAlphaPresets(),
    enabled: editing, staleTime: 60_000,
  });

  const statusMutation = useMutation({
    mutationFn: ({ status, alias }: { status: string; alias?: string }) =>
      experimentsApi.setStatus(expName, status, alias),
    onSuccess: () => qc.invalidateQueries({ queryKey: ['experiment', expName] }),
  });

  const updateMutation = useMutation({
    mutationFn: (updatedConfig: any) => experimentsApi.update(expName, updatedConfig),
    onSuccess: () => {
      qc.invalidateQueries({ queryKey: ['experiment', expName] });
      qc.invalidateQueries({ queryKey: ['experiments'] });
      setEditing(false);
      setDraft(null);
    },
  });

  const sqsComputeMutation = useMutation({
    mutationFn: () => sqsApi.compute(expName),
    onSuccess: (data) => setSqsResult(data),
  });

  const sqsRescoreMutation = useMutation({
    mutationFn: () => sqsApi.rescore(expName),
    onSuccess: (data) => {
      setSqsResult(data);
      qc.invalidateQueries({ queryKey: ['experiment', expName] });
      qc.invalidateQueries({ queryKey: ['leaderboard'] });
    },
  });

  const [pipelineId, setPipelineId] = useState<string | null>(null);
  const [pipelineStep, setPipelineStep] = useState<string>('');

  const sqsPipelineMutation = useMutation({
    mutationFn: () => sqsApi.pipeline(expName),
    onSuccess: (data) => {
      if (data.pipeline_status === 'existing_entry') {
        setSqsResult(data as SqsResult);
        return;
      }
      if (data.pipeline_id) {
        setPipelineId(data.pipeline_id);
        setPipelineStep(data.step || 'Starting…');
      }
    },
  });

  // Poll pipeline until done
  useEffect(() => {
    if (!pipelineId) return;
    const interval = setInterval(async () => {
      try {
        const data = await sqsApi.pollPipeline(pipelineId);
        setPipelineStep(data.step || '');
        if (data.pipeline_status === 'completed') {
          clearInterval(interval);
          setPipelineId(null);
          setSqsResult(data as SqsResult);
          qc.invalidateQueries({ queryKey: ['experiment', expName] });
          qc.invalidateQueries({ queryKey: ['leaderboard'] });
        } else if (data.pipeline_status === 'failed') {
          clearInterval(interval);
          setPipelineId(null);
          setSqsResult({ ...(data as any), pending_reason: data.error || 'pipeline failed' });
        }
      } catch {
        clearInterval(interval);
        setPipelineId(null);
      }
    }, 2000);
    return () => clearInterval(interval);
  }, [pipelineId]);

  // Auto-enter edit mode when ?edit=true in URL
  useEffect(() => {
    if (config && searchParams.get('edit') === 'true' && !editing) {
      const d = JSON.parse(JSON.stringify(config));
      setDraft(d);
      setRawJsonText(JSON.stringify(d, null, 2));
      setRawJsonError(null);
      setTagInput('');
      setEditing(true);
    }
  }, [config, searchParams]);

  // Sync rawJsonText when entering raw tab while editing
  useEffect(() => {
    if (editing && tab === 'raw' && draft) {
      setRawJsonText(JSON.stringify(draft, null, 2));
      setRawJsonError(null);
    }
  }, [tab, editing]);

  if (isLoading) return <div style={{ padding: 32 }}><Loading /></div>;
  if (error) return <div style={{ padding: 32 }}><ErrorState error={error as Error} /></div>;
  if (!config) return null;

  const perf = config.performance_summary as Record<string, number> | null;
  const displayConfig = editing ? draft : config;
  const bakedSleeves = extractBakedSleeves(displayConfig);

  // --- Edit helpers ---
  function startEditing() {
    const d = JSON.parse(JSON.stringify(config));
    setDraft(d);
    setRawJsonText(JSON.stringify(d, null, 2));
    setRawJsonError(null);
    setTagInput('');
    setEditing(true);
  }

  function cancelEditing() {
    setDraft(null);
    setEditing(false);
    setRawJsonError(null);
  }

  function updateDraft(path: string[], value: any) {
    setDraft((prev: any) => {
      const next = JSON.parse(JSON.stringify(prev));
      let obj = next;
      for (let i = 0; i < path.length - 1; i++) {
        if (obj[path[i]] == null) obj[path[i]] = {};
        obj = obj[path[i]];
      }
      const key = path[path.length - 1];
      if (value === '' || value === null || value === undefined) {
        delete obj[key];
      } else {
        obj[key] = value;
      }
      return next;
    });
  }

  function handleSave() {
    if (tab === 'raw') {
      try {
        const parsed = JSON.parse(rawJsonText);
        updateMutation.mutate(parsed);
      } catch (e) {
        setRawJsonError(`JSON parse error: ${(e as Error).message}`);
      }
    } else {
      updateMutation.mutate(draft);
    }
  }

  function addTag(tag: string) {
    const t = tag.trim();
    if (!t) return;
    const current: string[] = draft?.tags ?? [];
    if (!current.includes(t)) {
      updateDraft(['tags'], [...current, t]);
    }
    setTagInput('');
  }

  function removeTag(tag: string) {
    const current: string[] = draft?.tags ?? [];
    updateDraft(['tags'], current.filter(t => t !== tag));
  }

  // Sleeve value helpers
  function getSleeveValue(key: string, nested?: string): string {
    if (!draft) return '';
    const ov = draft.overrides ?? {};
    if (nested) return ov?.[nested]?.[key] ?? '';
    return ov?.[key] ?? '';
  }

  function setSleeveValue(key: string, value: string, nested?: string) {
    if (nested) {
      updateDraft(['overrides', nested, key], value);
    } else {
      updateDraft(['overrides', key], value);
    }
  }

  // Numeric override helper
  function getOverrideNum(section: string, key: string): number | undefined {
    return (displayConfig as any)?.overrides?.[section]?.[key];
  }
  function setOverrideNum(section: string, key: string, value: number | null) {
    updateDraft(['overrides', section, key], value);
  }

  const TABS: { id: Tab; label: string }[] = [
    { id: 'overview', label: 'Overview' },
    { id: 'engines', label: `Engines (${config.strategy_engines?.length ?? 0})` },
    { id: 'tree', label: 'Tree' },
    { id: 'runs', label: 'Runs' },
    { id: 'raw', label: editing ? 'JSON ✏' : 'JSON' },
  ];

  // ancestor chain: API returns [root, ..., parent, current]
  const ancestorChain = (lineage?.ancestor_chain ?? []) as { name: string; status: string }[];
  const ancestors = ancestorChain.slice(0, -1);

  const actionBtn = (label: string, icon: React.ReactNode, onClick: () => void, accent: string, disabled = false) => (
    <button
      onClick={onClick}
      disabled={disabled}
      style={{
        display: 'flex', alignItems: 'center', gap: 6,
        padding: '7px 14px', borderRadius: 7, fontSize: 13, fontWeight: 500,
        background: `color-mix(in srgb, ${accent} 8%, transparent)`,
        border: `1px solid color-mix(in srgb, ${accent} 18%, transparent)`,
        color: disabled ? 'var(--text3)' : accent,
        cursor: disabled ? 'not-allowed' : 'pointer',
        transition: 'all 0.12s', opacity: disabled ? 0.5 : 1,
      }}
      onMouseEnter={e => { if (!disabled) (e.currentTarget as HTMLButtonElement).style.background = `color-mix(in srgb, ${accent} 14%, transparent)`; }}
      onMouseLeave={e => { if (!disabled) (e.currentTarget as HTMLButtonElement).style.background = `color-mix(in srgb, ${accent} 8%, transparent)`; }}
    >
      {icon}{label}
    </button>
  );

  const sectionLabel = (text: string) => (
    <div style={{ fontFamily: 'var(--font-mono)', fontSize: 11, letterSpacing: '0.10em', textTransform: 'uppercase', color: 'var(--text3)', marginBottom: 10 }}>
      {text}
    </div>
  );

  return (
    <div style={{ padding: '36px 40px', paddingBottom: editing ? 100 : 36 }} className="fade-up">
      {/* Breadcrumb */}
      <div style={{ display: 'flex', alignItems: 'center', gap: 6, marginBottom: 18, fontFamily: 'var(--font-mono)', fontSize: 13, color: 'var(--text3)' }}>
        <Link to="/experiments" style={{ color: 'var(--text3)', textDecoration: 'none' }}>strategies</Link>
        <ChevronRight size={13} />
        <span style={{ color: 'var(--text2)' }}>{expName}</span>
        {editing && <span style={{ color: 'var(--cyan)', marginLeft: 4 }}>· editing</span>}
      </div>

      {/* Header */}
      <div style={{ display: 'flex', alignItems: 'flex-start', justifyContent: 'space-between', marginBottom: 24, gap: 16 }}>
        <div>
          <div style={{ display: 'flex', alignItems: 'center', gap: 10, marginBottom: 8, flexWrap: 'wrap' }}>
            <h1 style={{ fontFamily: 'var(--font-mono)', fontSize: 24, fontWeight: 700, color: 'var(--text1)' }}>
              {expName}
            </h1>
            <StatusBadge status={config.status} size="md" />
            {config.aliases?.map(a => (
              <span key={a} style={{
                fontSize: 12, fontFamily: 'var(--font-mono)',
                background: 'var(--purple-dim)', color: 'var(--purple)',
                border: '1px solid rgba(124,58,237,0.18)',
                padding: '2px 8px', borderRadius: 4, letterSpacing: '0.03em',
              }}>
                {a}
              </span>
            ))}
          </div>
        </div>
        <div style={{ display: 'flex', gap: 8, flexShrink: 0, flexWrap: 'wrap' }}>
          {!editing && actionBtn('Run Backtest', <Play size={13} />, () => navigate(`/backtest?exp=${encodeURIComponent(expName)}`), 'var(--orange)')}
          {!editing && config.status !== 'promoted' && actionBtn('Pin', <Pin size={13} />, () => statusMutation.mutate({ status: 'promoted' }), 'var(--green)')}
          {!editing && config.status === 'promoted' && actionBtn('Unpin', <Pin size={13} />, () => statusMutation.mutate({ status: 'active' }), 'var(--text3)')}
          {!editing && config.status === 'active' && actionBtn('Archive', <Archive size={13} />, () => statusMutation.mutate({ status: 'retired' }), 'var(--text3)')}
          {!editing && actionBtn('Edit', <Pencil size={13} />, startEditing, 'var(--cyan)')}
          {editing && actionBtn('Cancel', <X size={13} />, cancelEditing, 'var(--text3)')}
        </div>
      </div>

      {/* Description / Changelog card */}
      {!editing && (config.description || config.changelog) && (
        <div style={{
          background: 'var(--bg1)', border: '1px solid var(--border)', borderRadius: 12,
          padding: '18px 22px', marginBottom: 24,
          boxShadow: '0 1px 3px rgba(0,0,0,0.04)',
          display: 'flex', flexDirection: 'column', gap: 14,
        }}>
          {config.description && (
            <div>
              {sectionLabel('Description')}
              <p style={{ fontSize: 15, color: 'var(--text1)', lineHeight: 1.7, margin: 0, whiteSpace: 'pre-wrap' }}>
                {config.description}
              </p>
            </div>
          )}
          {config.changelog && (
            <div style={{ borderTop: config.description ? '1px solid var(--border)' : 'none', paddingTop: config.description ? 14 : 0 }}>
              {sectionLabel('Changelog')}
              <p style={{ fontSize: 14, color: 'var(--text2)', lineHeight: 1.7, margin: 0, whiteSpace: 'pre-wrap', fontFamily: 'var(--font-mono)' }}>
                {config.changelog}
              </p>
            </div>
          )}
        </div>
      )}

      {/* Edit: text fields card */}
      {editing && draft && (
        <div style={{
          background: 'var(--bg1)', border: '1px solid color-mix(in srgb, var(--cyan) 30%, var(--border))',
          borderRadius: 12, padding: '20px 22px', marginBottom: 20,
          boxShadow: '0 1px 3px rgba(0,0,0,0.04)',
          display: 'flex', flexDirection: 'column', gap: 16,
        }}>
          {/* Description */}
          <div>
            {sectionLabel('Description')}
            <textarea
              value={draft.description ?? ''}
              onChange={e => updateDraft(['description'], e.target.value)}
              rows={3}
              placeholder="Strategy description..."
              style={{ ...inputStyle, resize: 'vertical', minHeight: 70 }}
            />
          </div>
          {/* Changelog */}
          <div>
            {sectionLabel('Changelog')}
            <textarea
              value={draft.changelog ?? ''}
              onChange={e => updateDraft(['changelog'], e.target.value)}
              rows={2}
              placeholder="What changed?"
              style={{ ...inputStyle, resize: 'vertical', minHeight: 52 }}
            />
          </div>
          {/* Tags */}
          <div>
            {sectionLabel('Tags')}
            <div style={{ display: 'flex', flexWrap: 'wrap', gap: 6, marginBottom: 8 }}>
              {(draft.tags ?? []).map((t: string) => (
                <span key={t} style={{
                  display: 'inline-flex', alignItems: 'center', gap: 4,
                  fontFamily: 'var(--font-mono)', fontSize: 12,
                  background: 'var(--bg2)', color: 'var(--text2)',
                  border: '1px solid var(--border-md)', padding: '2px 8px', borderRadius: 5,
                }}>
                  {t}
                  <button
                    onClick={() => removeTag(t)}
                    style={{ display: 'flex', background: 'none', border: 'none', cursor: 'pointer', color: 'var(--text3)', padding: 0 }}
                  >
                    <X size={10} />
                  </button>
                </span>
              ))}
            </div>
            <input
              type="text"
              placeholder="Add tag (Enter)..."
              value={tagInput}
              onChange={e => setTagInput(e.target.value)}
              onKeyDown={e => { if (e.key === 'Enter') { e.preventDefault(); addTag(tagInput); } }}
              style={{ ...inputStyle, maxWidth: 260, fontSize: 13, padding: '5px 10px' }}
            />
          </div>
        </div>
      )}

      {/* Baked sleeves — view mode */}
      {!editing && bakedSleeves.length > 0 && (
        <div style={{
          background: 'var(--bg1)', border: '1px solid var(--border)', borderRadius: 12,
          padding: '14px 20px', marginBottom: 20,
          boxShadow: '0 1px 3px rgba(0,0,0,0.04)',
        }}>
          {sectionLabel('Baked Sleeves')}
          <div style={{ display: 'flex', flexWrap: 'wrap', gap: 10 }}>
            {bakedSleeves.map(s => <SleeveBadge key={s.label} {...s} />)}
          </div>
        </div>
      )}

      {/* Edit: sleeve selects */}
      {editing && draft && (
        <div style={{
          background: 'var(--bg1)', border: '1px solid color-mix(in srgb, var(--cyan) 30%, var(--border))',
          borderRadius: 12, padding: '20px 22px', marginBottom: 20,
          boxShadow: '0 1px 3px rgba(0,0,0,0.04)',
        }}>
          {sectionLabel('Baked Sleeves')}
          <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 14 }}>
            <SleeveSelect
              label="Cash Parking" color="var(--orange)"
              value={getSleeveValue('cash_parking_preset', 'risk')}
              onChange={v => setSleeveValue('cash_parking_preset', v, 'risk')}
              presetsData={parkingPresetsData}
            />
            <SleeveSelect
              label="Idle Alpha" color="var(--green)"
              value={getSleeveValue('idle_alpha_sleeve_preset')}
              onChange={v => setSleeveValue('idle_alpha_sleeve_preset', v)}
              presetsData={idleAlphaPresetsData}
            />
            <SleeveSelect
              label="Form 4 Sleeve" color="var(--cyan)"
              value={getSleeveValue('form4_capture_sleeve_preset')}
              onChange={v => setSleeveValue('form4_capture_sleeve_preset', v)}
              presetsData={form4PresetsData}
            />
            <SleeveSelect
              label="Ownership Sleeve" color="var(--violet, var(--cyan))"
              value={getSleeveValue('ownership_capture_sleeve_preset')}
              onChange={v => setSleeveValue('ownership_capture_sleeve_preset', v)}
              presetsData={ownershipPresetsData}
            />
            <SleeveSelect
              label="Risk-Off Alpha" color="var(--red)"
              value={getSleeveValue('risk_off_alpha_sleeve_preset')}
              onChange={v => setSleeveValue('risk_off_alpha_sleeve_preset', v)}
              presetsData={riskOffPresetsData}
            />
          </div>
        </div>
      )}

      {/* Key metrics */}
      {perf && (
        <div style={{ display: 'grid', gridTemplateColumns: 'repeat(6, 1fr)', gap: 10, marginBottom: 24 }}>
          <MetricCard label="SQS" value={fmt(perf.sqs_score)} color="var(--gold)" />
          <MetricCard label="Test Return" value={fmtPct(perf.test_total_return_pct)} color={(perf.test_total_return_pct ?? 0) >= 0 ? 'var(--green)' : 'var(--red)'} />
          <MetricCard label="Valid Return" value={fmtPct(perf.valid_total_return_pct)} color="var(--text1)" />
          <MetricCard label="Max DD" value={fmtPct(perf.test_max_drawdown_pct)} color="var(--red)" />
          <MetricCard label="Win Rate" value={fmtPct(perf.test_win_rate)} color="var(--text1)" />
          <MetricCard label="PF" value={fmt(perf.test_profit_factor, 2)} color="var(--cyan)" />
        </div>
      )}

      {/* Tabs */}
      <div style={{ display: 'flex', gap: 2, marginBottom: 20, borderBottom: '1px solid var(--border)' }}>
        {TABS.map(t => (
          <button
            key={t.id}
            onClick={() => setTab(t.id)}
            style={{
              padding: '9px 18px',
              fontSize: 16, fontWeight: 500,
              border: 'none',
              background: 'none',
              cursor: 'pointer',
              transition: 'all 0.12s',
              borderBottom: `2px solid ${tab === t.id ? 'var(--cyan)' : 'transparent'}`,
              marginBottom: -1,
              color: tab === t.id ? 'var(--cyan)' : 'var(--text3)',
            }}
          >
            {t.label}
          </button>
        ))}
      </div>

      {/* Tab content */}
      {tab === 'overview' && (
        <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 16 }}>
          {/* Metadata */}
          <div style={{ background: 'var(--bg1)', border: '1px solid var(--border)', borderRadius: 12, padding: '18px 20px', boxShadow: '0 1px 3px rgba(0,0,0,0.04)' }}>
            <div style={{ fontSize: 13, fontWeight: 600, color: 'var(--text2)', marginBottom: 16, letterSpacing: '0.04em', textTransform: 'uppercase' }}>
              Metadata
            </div>
            <dl style={{ display: 'flex', flexDirection: 'column', gap: 10 }}>
              {[
                { label: 'ID', value: config.id ?? '—' },
                { label: 'Ancestors', value: ancestors.length > 0 ? (
                  <div style={{ display: 'flex', alignItems: 'center', flexWrap: 'wrap', gap: 4 }}>
                    {ancestors.map((a, i) => (
                      <span key={a.name} style={{ display: 'flex', alignItems: 'center', gap: 4 }}>
                        {i > 0 && <span style={{ color: 'var(--text3)' }}>›</span>}
                        <Link to={`/experiments/${encodeURIComponent(a.name)}`} style={{ fontFamily: 'var(--font-mono)', fontSize: 13, color: 'var(--cyan)', textDecoration: 'none' }}>
                          {a.name}
                        </Link>
                      </span>
                    ))}
                  </div>
                ) : '—' },
                { label: 'Family', value: (config as any).version_family ?? '—' },
                { label: 'Generation', value: (config as any).generation != null ? `gen ${(config as any).generation}` : '—' },
                { label: 'Created', value: fmtDate((config as any).created_at) },
                { label: 'Created by', value: (config as any).created_by ?? '—' },
              ].map(({ label, value }) => (
                <div key={label} style={{ display: 'flex', gap: 14, alignItems: 'flex-start' }}>
                  <dt style={{ width: 96, flexShrink: 0, fontSize: 13, color: 'var(--text3)', fontFamily: 'var(--font-mono)' }}>
                    {label}
                  </dt>
                  <dd style={{ fontSize: 15, color: 'var(--text1)', fontFamily: 'var(--font-mono)' }}>
                    {value as React.ReactNode}
                  </dd>
                </div>
              ))}
            </dl>
          </div>

          <div style={{ display: 'flex', flexDirection: 'column', gap: 14 }}>
            {!editing && (config as any).changelog && (
              <div style={{ background: 'var(--bg1)', border: '1px solid var(--border)', borderRadius: 12, padding: '16px 18px', boxShadow: '0 1px 3px rgba(0,0,0,0.04)' }}>
                <div style={{ fontSize: 13, fontWeight: 600, color: 'var(--text2)', marginBottom: 10, textTransform: 'uppercase', letterSpacing: '0.04em' }}>Changelog</div>
                <p style={{ fontSize: 15, color: 'var(--text2)', lineHeight: 1.65, whiteSpace: 'pre-wrap' }}>{(config as any).changelog}</p>
              </div>
            )}
            {!editing && config.tags?.length > 0 && (
              <div style={{ background: 'var(--bg1)', border: '1px solid var(--border)', borderRadius: 12, padding: '16px 18px', boxShadow: '0 1px 3px rgba(0,0,0,0.04)' }}>
                <div style={{ fontSize: 13, fontWeight: 600, color: 'var(--text2)', marginBottom: 10, textTransform: 'uppercase', letterSpacing: '0.04em' }}>Tags</div>
                <div style={{ display: 'flex', flexWrap: 'wrap', gap: 6 }}>
                  {config.tags.map(t => (
                    <span key={t} style={{
                      fontSize: 13, fontFamily: 'var(--font-mono)',
                      background: 'var(--bg2)', color: 'var(--text2)',
                      border: '1px solid var(--border-md)', padding: '3px 9px', borderRadius: 5,
                    }}>
                      {t}
                    </span>
                  ))}
                </div>
              </div>
            )}

            {/* SQS panel */}
            {!editing && (
              <SqsPanel
                result={sqsResult}
                isLoading={sqsComputeMutation.isPending}
                isRescoring={sqsRescoreMutation.isPending}
                isPipelining={sqsPipelineMutation.isPending || !!pipelineId}
                pipelineStep={pipelineStep}
                onCompute={() => sqsComputeMutation.mutate()}
                onRescore={() => sqsRescoreMutation.mutate()}
                onPipeline={() => sqsPipelineMutation.mutate()}
                hasJournalEntry={(config as any).has_journal_entry === true}
                experimentName={expName}
              />
            )}

            {/* Edit: key numeric overrides */}
            {editing && draft && (
              <div style={{ background: 'var(--bg1)', border: '1px solid color-mix(in srgb, var(--cyan) 30%, var(--border))', borderRadius: 12, padding: '16px 18px', boxShadow: '0 1px 3px rgba(0,0,0,0.04)', display: 'flex', flexDirection: 'column', gap: 16 }}>
                {/* Signal */}
                {(getOverrideNum('signal', 'score_threshold') !== undefined ||
                  getOverrideNum('signal', 'a_tier_score_threshold') !== undefined ||
                  getOverrideNum('signal', 'max_candidates_per_day') !== undefined) && (
                  <div>
                    {sectionLabel('Signal')}
                    <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
                      <NumericField label="score_threshold" value={getOverrideNum('signal', 'score_threshold')} onChange={v => setOverrideNum('signal', 'score_threshold', v)} />
                      <NumericField label="a_tier_score_threshold" value={getOverrideNum('signal', 'a_tier_score_threshold')} onChange={v => setOverrideNum('signal', 'a_tier_score_threshold', v)} />
                      <NumericField label="max_candidates_per_day" value={getOverrideNum('signal', 'max_candidates_per_day')} onChange={v => setOverrideNum('signal', 'max_candidates_per_day', v)} />
                    </div>
                  </div>
                )}
                {/* Risk */}
                {(getOverrideNum('risk', 'per_trade_risk_pct') !== undefined ||
                  getOverrideNum('risk', 'max_positions') !== undefined ||
                  getOverrideNum('risk', 'stop_atr_multiplier') !== undefined) && (
                  <div>
                    {sectionLabel('Risk')}
                    <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
                      <NumericField label="per_trade_risk_pct" value={getOverrideNum('risk', 'per_trade_risk_pct')} onChange={v => setOverrideNum('risk', 'per_trade_risk_pct', v)} />
                      <NumericField label="max_positions" value={getOverrideNum('risk', 'max_positions')} onChange={v => setOverrideNum('risk', 'max_positions', v)} />
                      <NumericField label="stop_atr_multiplier" value={getOverrideNum('risk', 'stop_atr_multiplier')} onChange={v => setOverrideNum('risk', 'stop_atr_multiplier', v)} />
                    </div>
                  </div>
                )}
                {/* Execution */}
                {(getOverrideNum('execution', 'max_holding_days') !== undefined ||
                  getOverrideNum('execution', 'trailing_warmup_days') !== undefined ||
                  getOverrideNum('execution', 'a_tier_target_1_r') !== undefined) && (
                  <div>
                    {sectionLabel('Execution')}
                    <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
                      <NumericField label="max_holding_days" value={getOverrideNum('execution', 'max_holding_days')} onChange={v => setOverrideNum('execution', 'max_holding_days', v)} />
                      <NumericField label="trailing_warmup_days" value={getOverrideNum('execution', 'trailing_warmup_days')} onChange={v => setOverrideNum('execution', 'trailing_warmup_days', v)} />
                      <NumericField label="a_tier_target_1_r" value={getOverrideNum('execution', 'a_tier_target_1_r')} onChange={v => setOverrideNum('execution', 'a_tier_target_1_r', v)} />
                    </div>
                  </div>
                )}
                <div style={{ fontSize: 12, color: 'var(--text3)', fontFamily: 'var(--font-mono)', paddingTop: 4, borderTop: '1px solid var(--border)' }}>
                  tip: 모든 필드는 JSON 탭에서 직접 편집 가능
                </div>
              </div>
            )}
          </div>
        </div>
      )}

      {tab === 'engines' && (
        <div style={{ display: 'flex', flexDirection: 'column', gap: 14 }}>
          {config.strategy_engines?.map((engine: any, i: number) => (
            <div key={engine.engine_id ?? i} style={{ background: 'var(--bg1)', border: '1px solid var(--border)', borderRadius: 12, padding: '16px 18px', boxShadow: '0 1px 3px rgba(0,0,0,0.04)' }}>
              <div style={{ fontFamily: 'var(--font-mono)', fontSize: 15, fontWeight: 600, color: 'var(--cyan)', marginBottom: 12 }}>
                {engine.engine_id ?? `engine_${i}`}
              </div>
              <pre style={{ fontSize: 12, color: 'var(--text2)', background: 'var(--bg2)', borderRadius: 7, padding: 14, overflow: 'auto', maxHeight: 300, fontFamily: 'var(--font-mono)', lineHeight: 1.65 }}>
                {JSON.stringify(engine, null, 2)}
              </pre>
            </div>
          ))}
          {editing && (
            <div style={{ fontSize: 12, color: 'var(--text3)', fontFamily: 'var(--font-mono)', padding: '10px 0' }}>
              엔진 편집은 JSON 탭에서 직접 수정하세요.
            </div>
          )}
        </div>
      )}

      {tab === 'tree' && (
        <div>
          {lineage
            ? <LineageTree tree={lineage.tree} ancestorChain={lineage.ancestor_chain as any[]} current={expName} />
            : <Loading />}
        </div>
      )}

      {tab === 'runs' && (
        <div>
          {runs ? (
            runs.runs.length === 0
              ? <div style={{ padding: '56px 0', textAlign: 'center', color: 'var(--text3)', fontFamily: 'var(--font-mono)', fontSize: 15 }}>no runs found</div>
              : (
                <div style={{ background: 'var(--bg1)', border: '1px solid var(--border)', borderRadius: 12, overflow: 'hidden', boxShadow: '0 1px 3px rgba(0,0,0,0.04)' }}>
                  {(runs.runs as any[]).map((run, i) => (
                    <div
                      key={run.run_id}
                      onClick={() => navigate(`/backtest/results/${run.run_id}`)}
                      style={{
                        display: 'flex', alignItems: 'center', gap: 14, padding: '11px 18px',
                        borderBottom: i < runs.runs.length - 1 ? '1px solid var(--border)' : 'none',
                        cursor: 'pointer', transition: 'background 0.1s',
                      }}
                      onMouseEnter={e => (e.currentTarget.style.background = 'var(--cyan-dim)')}
                      onMouseLeave={e => (e.currentTarget.style.background = 'transparent')}
                    >
                      <span style={{ fontFamily: 'var(--font-mono)', fontSize: 15, color: 'var(--text2)', flex: 1, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
                        {run.run_id}
                      </span>
                      <span style={{ fontFamily: 'var(--font-mono)', fontSize: 12, color: 'var(--cyan)', textTransform: 'uppercase', width: 44 }}>
                        {run.split_name}
                      </span>
                      <span style={{ fontFamily: 'var(--font-mono)', fontSize: 13, color: 'var(--text3)', width: 76, textAlign: 'right' }}>
                        {fmtDate(run.started_at)}
                      </span>
                      <ExternalLink size={13} style={{ color: 'var(--text3)', flexShrink: 0 }} />
                    </div>
                  ))}
                </div>
              )
          ) : <Loading />}
        </div>
      )}

      {tab === 'raw' && !editing && (
        <pre style={{
          background: 'var(--bg1)', border: '1px solid var(--border)', borderRadius: 12,
          padding: 18, fontSize: 12, color: 'var(--text2)', overflow: 'auto', maxHeight: '70vh',
          fontFamily: 'var(--font-mono)', lineHeight: 1.7,
          boxShadow: '0 1px 3px rgba(0,0,0,0.04)',
        }}>
          {JSON.stringify(config, null, 2)}
        </pre>
      )}

      {tab === 'raw' && editing && (
        <div>
          {rawJsonError && (
            <div style={{
              padding: '10px 14px', marginBottom: 10,
              background: 'color-mix(in srgb, var(--red) 8%, transparent)',
              border: '1px solid color-mix(in srgb, var(--red) 25%, transparent)',
              borderRadius: 8, color: 'var(--red)', fontSize: 13, fontFamily: 'var(--font-mono)',
            }}>
              {rawJsonError}
            </div>
          )}
          <textarea
            value={rawJsonText}
            onChange={e => {
              setRawJsonText(e.target.value);
              try { JSON.parse(e.target.value); setRawJsonError(null); }
              catch (err) { setRawJsonError(`JSON: ${(err as Error).message}`); }
            }}
            style={{
              width: '100%', boxSizing: 'border-box',
              background: 'var(--bg1)', border: '1px solid color-mix(in srgb, var(--cyan) 30%, var(--border))',
              borderRadius: 12, padding: 18, fontSize: 12, color: 'var(--text2)',
              fontFamily: 'var(--font-mono)', lineHeight: 1.7,
              minHeight: '60vh', resize: 'vertical', outline: 'none',
            }}
            spellCheck={false}
          />
        </div>
      )}

      {/* Save bar (fixed bottom, only when editing) */}
      {editing && (
        <div style={{
          position: 'fixed', bottom: 0, left: 240, right: 0,
          background: 'var(--bg1)', borderTop: '1px solid var(--border)',
          padding: '14px 40px', display: 'flex', alignItems: 'center', gap: 12,
          zIndex: 100, boxShadow: '0 -4px 16px rgba(0,0,0,0.08)',
        }}>
          <button
            onClick={handleSave}
            disabled={updateMutation.isPending || (tab === 'raw' && !!rawJsonError)}
            style={{
              display: 'flex', alignItems: 'center', gap: 7,
              padding: '9px 22px', fontSize: 14, fontWeight: 600, borderRadius: 8,
              cursor: (updateMutation.isPending || (tab === 'raw' && !!rawJsonError)) ? 'not-allowed' : 'pointer',
              background: 'var(--cyan-dim)', border: '1px solid rgba(0,119,182,0.35)',
              color: 'var(--cyan)', transition: 'all 0.12s',
              opacity: (updateMutation.isPending || (tab === 'raw' && !!rawJsonError)) ? 0.5 : 1,
            }}
          >
            <Save size={14} />
            {updateMutation.isPending ? 'Saving...' : 'Save Changes'}
          </button>
          <button
            onClick={cancelEditing}
            style={{
              padding: '9px 18px', fontSize: 14, borderRadius: 8,
              background: 'none', border: '1px solid var(--border-md)',
              color: 'var(--text3)', cursor: 'pointer',
            }}
          >
            Discard
          </button>
          {updateMutation.isError && (
            <span style={{ fontFamily: 'var(--font-mono)', fontSize: 13, color: 'var(--red)' }}>
              {(updateMutation.error as Error).message}
            </span>
          )}
        </div>
      )}
    </div>
  );
}
