/**
 * Shared reusable UI components: StatusBadge, ConfidenceBar, TrendArrow,
 * DateRangeSelector, TickerFilter, LoadingSpinner, ErrorBoundary.
 * Requirements: 13.1, 13.2
 */
import { Component, type ReactNode, type ChangeEvent } from 'react';
import { TrendingUp, TrendingDown, Minus, Loader2 } from 'lucide-react';

// ---------------------------------------------------------------------------
// StatusBadge
// ---------------------------------------------------------------------------

const statusColors: Record<string, string> = {
  completed: 'bg-green-900/40 text-green-400 border-green-700/50',
  success: 'bg-green-900/40 text-green-400 border-green-700/50',
  valid: 'bg-green-900/40 text-green-400 border-green-700/50',
  active: 'bg-green-900/40 text-green-400 border-green-700/50',
  approved: 'bg-green-900/40 text-green-400 border-green-700/50',
  filled: 'bg-green-900/40 text-green-400 border-green-700/50',
  extracted: 'bg-green-900/40 text-green-400 border-green-700/50',
  running: 'bg-blue-900/40 text-blue-400 border-blue-700/50',
  pending: 'bg-yellow-900/40 text-yellow-400 border-yellow-700/50',
  parsed: 'bg-yellow-900/40 text-yellow-400 border-yellow-700/50',
  failed: 'bg-red-900/40 text-red-400 border-red-700/50',
  rejected: 'bg-red-900/40 text-red-400 border-red-700/50',
  extraction_failed: 'bg-red-900/40 text-red-400 border-red-700/50',
  low_quality: 'bg-orange-900/40 text-orange-400 border-orange-700/50',
  cancelled: 'bg-gray-800/40 text-gray-400 border-gray-700/50',
  disabled: 'bg-gray-800/40 text-gray-400 border-gray-700/50',
  paper: 'bg-purple-900/40 text-purple-400 border-purple-700/50',
  live: 'bg-orange-900/40 text-orange-400 border-orange-700/50',
  buy: 'bg-green-900/40 text-green-400 border-green-700/50',
  sell: 'bg-red-900/40 text-red-400 border-red-700/50',
  hold: 'bg-yellow-900/40 text-yellow-400 border-yellow-700/50',
  watch: 'bg-blue-900/40 text-blue-400 border-blue-700/50',
  high: 'bg-green-900/40 text-green-400 border-green-700/50',
  medium: 'bg-yellow-900/40 text-yellow-400 border-yellow-700/50',
  low: 'bg-red-900/40 text-red-400 border-red-700/50',
};

export function StatusBadge({ status }: { status: string | null | undefined }) {
  const s = (status ?? 'unknown').toLowerCase();
  const cls = statusColors[s] ?? 'bg-gray-800/40 text-gray-400 border-gray-700/50';
  return (
    <span className={`inline-block rounded-full border px-2 py-0.5 text-xs font-medium ${cls}`}>
      {s}
    </span>
  );
}

// ---------------------------------------------------------------------------
// ConfidenceBar
// ---------------------------------------------------------------------------

export function ConfidenceBar({ value, className = '' }: { value: number | null | undefined; className?: string }) {
  const pct = Math.round((value ?? 0) * 100);
  const color = pct >= 70 ? 'bg-green-500' : pct >= 40 ? 'bg-yellow-500' : 'bg-red-500';
  return (
    <div className={`flex items-center gap-2 ${className}`} role="meter" aria-valuenow={pct} aria-valuemin={0} aria-valuemax={100} aria-label={`Confidence ${pct}%`}>
      <div className="h-1.5 w-20 rounded-full bg-surface-700">
        <div className={`h-full rounded-full ${color}`} style={{ width: `${pct}%` }} />
      </div>
      <span className="text-xs text-gray-400">{pct}%</span>
    </div>
  );
}

// ---------------------------------------------------------------------------
// TrendArrow
// ---------------------------------------------------------------------------

export function TrendArrow({ direction }: { direction: string | null | undefined }) {
  const d = (direction ?? 'neutral').toLowerCase();
  if (d === 'bullish') return <TrendingUp size={16} className="text-green-400" aria-label="Bullish" />;
  if (d === 'bearish') return <TrendingDown size={16} className="text-red-400" aria-label="Bearish" />;
  return <Minus size={16} className="text-gray-500" aria-label={d === 'mixed' ? 'Mixed' : 'Neutral'} />;
}

// ---------------------------------------------------------------------------
// DateRangeSelector
// ---------------------------------------------------------------------------

export function DateRangeSelector({ value, onChange }: { value: number; onChange: (hours: number) => void }) {
  const options = [
    { label: '1h', hours: 1 },
    { label: '6h', hours: 6 },
    { label: '24h', hours: 24 },
    { label: '7d', hours: 168 },
  ];
  return (
    <div className="inline-flex rounded-md border border-surface-700" role="group" aria-label="Time range">
      {options.map((opt) => (
        <button
          key={opt.hours}
          onClick={() => onChange(opt.hours)}
          className={`px-3 py-1 text-xs font-medium transition-colors first:rounded-l-md last:rounded-r-md ${
            value === opt.hours ? 'bg-brand-600 text-white' : 'bg-surface-900 text-gray-400 hover:bg-surface-800'
          }`}
          aria-pressed={value === opt.hours}
        >
          {opt.label}
        </button>
      ))}
    </div>
  );
}

// ---------------------------------------------------------------------------
// TickerFilter
// ---------------------------------------------------------------------------

export function TickerFilter({ value, onChange }: { value: string; onChange: (v: string) => void }) {
  return (
    <input
      type="text"
      placeholder="Ticker…"
      value={value}
      onChange={(e: ChangeEvent<HTMLInputElement>) => onChange(e.target.value.toUpperCase())}
      className="w-24 rounded-md border border-surface-700 bg-surface-900 px-2 py-1 text-xs text-gray-200 placeholder-gray-500 focus:border-brand-500 focus:outline-none"
      aria-label="Filter by ticker"
    />
  );
}

// ---------------------------------------------------------------------------
// LoadingSpinner
// ---------------------------------------------------------------------------

export function LoadingSpinner({ className = '' }: { className?: string }) {
  return (
    <div className={`flex items-center justify-center py-12 ${className}`} role="status" aria-label="Loading">
      <Loader2 size={24} className="animate-spin text-brand-400" />
    </div>
  );
}

// ---------------------------------------------------------------------------
// ErrorBoundary
// ---------------------------------------------------------------------------

interface EBProps { children: ReactNode; fallback?: ReactNode }
interface EBState { error: Error | null }

export class ErrorBoundary extends Component<EBProps, EBState> {
  state: EBState = { error: null };

  static getDerivedStateFromError(error: Error) {
    return { error };
  }

  render() {
    if (this.state.error) {
      return this.props.fallback ?? (
        <div className="rounded-lg border border-red-700/50 bg-red-900/20 p-4 text-sm text-red-400" role="alert">
          Something went wrong: {this.state.error.message}
        </div>
      );
    }
    return this.props.children;
  }
}

// ---------------------------------------------------------------------------
// Card — generic container
// ---------------------------------------------------------------------------

export function Card({ children, className = '' }: { children: ReactNode; className?: string }) {
  return (
    <div className={`rounded-lg border border-surface-700 bg-surface-900 p-4 ${className}`}>
      {children}
    </div>
  );
}
