import { useState } from 'react';
import type { ScoredChunk } from '../types';
import { InfoTooltip } from './PipelineView';

interface SearchColumnState {
  status: 'idle' | 'running' | 'done';
  data?: { bm25Hits: ScoredChunk[]; vectorHits: ScoredChunk[] };
}

interface SearchColumnProps {
  state: SearchColumnState;
  accent: string;
  info: string;
}

function Spinner({ color }: { color: string }) {
  return (
    <span style={{
      display: 'inline-block',
      width: '14px',
      height: '14px',
      border: '2px solid var(--border)',
      borderTopColor: color,
      borderRadius: '50%',
      animation: 'spin 0.7s linear infinite',
    }} />
  );
}

function ScoreBadge({ score, source }: { score: number; source: 'bm25' | 'vector' }) {
  const label = source === 'bm25'
    ? score.toFixed(2)
    : (score * 100).toFixed(1) + '%';

  return (
    <span style={{
      padding: '0.1rem 0.35rem',
      borderRadius: '4px',
      background: 'var(--bg-card)',
      border: '1px solid var(--border)',
      color: 'var(--text-secondary)',
      fontFamily: "'SF Mono', 'Fira Code', 'Cascadia Code', monospace",
      fontSize: '0.65rem',
      fontWeight: 700,
      flexShrink: 0,
    }}>
      {label}
    </span>
  );
}

function HitRow({ hit }: { hit: ScoredChunk }) {
  const [open, setOpen] = useState(false);
  return (
    <div
      onClick={() => setOpen(o => !o)}
      style={{
        padding: '0.4rem 0.6rem',
        background: 'var(--bg-card)',
        border: '1px solid var(--border)',
        borderRadius: '5px',
        marginBottom: '0.25rem',
        cursor: 'pointer',
        fontSize: '0.75rem',
      }}
      onMouseEnter={e => { (e.currentTarget as HTMLDivElement).style.boxShadow = '0 1px 5px var(--shadow)'; }}
      onMouseLeave={e => { (e.currentTarget as HTMLDivElement).style.boxShadow = 'none'; }}
    >
      <div style={{ display: 'flex', alignItems: 'center', gap: '0.4rem' }}>
        <span style={{
          flex: 1,
          fontFamily: 'system-ui, -apple-system, sans-serif',
          fontWeight: 600,
          color: 'var(--text)',
          overflow: 'hidden',
          textOverflow: 'ellipsis',
          whiteSpace: 'nowrap',
          fontSize: '0.73rem',
        }}>
          {hit.chunk.title}
        </span>
        <ScoreBadge score={hit.score} source={hit.source} />
        <span style={{ color: 'var(--text-muted)', fontSize: '0.6rem' }}>{open ? '\u25B2' : '\u25BC'}</span>
      </div>
      {open && (
        <div style={{
          marginTop: '0.35rem',
          fontFamily: "'SF Mono', 'Fira Code', 'Cascadia Code', monospace",
          fontSize: '0.65rem',
          color: 'var(--text-secondary)',
          lineHeight: 1.5,
          whiteSpace: 'pre-wrap',
          wordBreak: 'break-word',
          borderTop: '1px solid var(--border-light)',
          paddingTop: '0.35rem',
        }}>
          {hit.chunk.text}
        </div>
      )}
    </div>
  );
}

// Deduplicate hits by docId, keeping the highest score per document.
function dedupeByDoc(hits: ScoredChunk[]): ScoredChunk[] {
  const best = new Map<string, ScoredChunk>();
  for (const hit of hits) {
    const existing = best.get(hit.chunk.docId);
    if (!existing || hit.score > existing.score) {
      best.set(hit.chunk.docId, hit);
    }
  }
  return [...best.values()].sort((a, b) => b.score - a.score);
}

function HitsSection({ label, hits, color, dedupe }: { label: string; hits: ScoredChunk[]; color: string; dedupe?: boolean }) {
  const displayHits = dedupe ? dedupeByDoc(hits) : hits;
  const top = displayHits.slice(0, 5);
  return (
    <div style={{ marginBottom: '0.7rem' }}>
      <div style={{
        fontSize: '0.68rem',
        fontWeight: 700,
        fontFamily: 'system-ui, -apple-system, sans-serif',
        color,
        textTransform: 'uppercase',
        letterSpacing: '0.06em',
        marginBottom: '0.35rem',
      }}>
        {label} <span style={{ color: 'var(--text-muted)', fontWeight: 400 }}>({displayHits.length} docs)</span>
      </div>
      {top.map((hit, i) => (
        <HitRow key={`${hit.chunk.docId}-${hit.chunk.chunkIndex}-${i}`} hit={hit} />
      ))}
      {displayHits.length > 5 && (
        <div style={{
          fontSize: '0.68rem',
          color: 'var(--text-muted)',
          fontFamily: 'system-ui, -apple-system, sans-serif',
          paddingLeft: '0.25rem',
        }}>
          +{displayHits.length - 5} more
        </div>
      )}
    </div>
  );
}

export default function SearchColumn({ state, accent, info }: SearchColumnProps) {
  const isIdle = state.status === 'idle';
  const isRunning = state.status === 'running';
  const isDone = state.status === 'done';

  return (
    <div style={{ opacity: isIdle ? 0.45 : 1, transition: 'opacity 0.3s' }}>
      <div style={{
        display: 'flex',
        alignItems: 'center',
        gap: '0.4rem',
        marginBottom: '0.75rem',
        paddingBottom: '0.5rem',
        borderBottom: '1px solid var(--stage-divider)',
      }}>
        <span style={{
          width: '3px',
          height: '14px',
          borderRadius: '2px',
          background: accent,
          flexShrink: 0,
        }} />
        <h3 style={{
          margin: 0,
          fontSize: '0.78rem',
          fontFamily: 'system-ui, -apple-system, sans-serif',
          fontWeight: 700,
          color: accent,
          textTransform: 'uppercase',
          letterSpacing: '0.05em',
        }}>
          Parallel Search
        </h3>
        {isRunning && <Spinner color={accent} />}
        <InfoTooltip text={info} />
      </div>

      {isIdle && (
        <p style={{ fontFamily: 'system-ui, -apple-system, sans-serif', fontSize: '0.75rem', color: 'var(--text-muted)', margin: 0 }}>
          Awaiting expansion...
        </p>
      )}

      {isRunning && (
        <p style={{ fontFamily: 'system-ui, -apple-system, sans-serif', fontSize: '0.75rem', color: 'var(--text-secondary)', margin: 0, fontStyle: 'italic' }}>
          Running vector + BM25 search...
        </p>
      )}

      {isDone && state.data && (
        <>
          <HitsSection
            label="Vector Search"
            hits={state.data.vectorHits}
            color="#00695c"
            dedupe
          />
          <HitsSection
            label="BM25 Search"
            hits={state.data.bm25Hits}
            color="#5c6bc0"
            dedupe
          />
        </>
      )}
    </div>
  );
}
