/**
 * Recommendation detail page with validation context.
 *
 * Shows original confidence alongside calibrated confidence (historical win rate),
 * evidence quality indicators, source reliability, and live eligibility status.
 *
 * Requirements: 13.1, 13.2, 13.3, 13.4, 13.5, 13.6, 13.7
 */
import { useParams, Link } from '@tanstack/react-router';
import { AlertTriangle, ShieldCheck, ShieldX, Info } from 'lucide-react';
import {
  useRecommendation,
  useValidationCalibration,
  useValidationGateStatus,
  useValidationAttributionSources,
} from '../api/hooks';
import { StatusBadge, ConfidenceBar, LoadingSpinner, Card } from '../components/ui';

export function RecommendationDetailPage() {
  const { id } = useParams({ from: '/recommendations/$id' });
  const { data: rec, isLoading } = useRecommendation(id);
  const { data: calibration } = useValidationCalibration();
  const { data: gateData } = useValidationGateStatus();
  const { data: sourcesData } = useValidationAttributionSources();

  if (isLoading || !rec) return <LoadingSpinner />;

  // --- Calibration: find the bucket matching this recommendation's confidence ---
  const matchingBucket = calibration?.buckets?.find(
    (b) => rec.confidence >= b.bucket_low && rec.confidence < b.bucket_high,
  );
  // Handle edge case: confidence of exactly 1.0 falls in the last bucket [0.90, 1.00]
  const calibratedBucket =
    matchingBucket ??
    (rec.confidence >= 1.0
      ? calibration?.buckets?.find((b) => b.bucket_high >= 1.0)
      : undefined);

  const historicalWinRate = calibratedBucket?.observed_win_rate;

  // --- Evidence counts ---
  const totalEvidenceCount = rec.evidence.length;
  // Compute duplicate evidence: group by normalized title, count extras
  const titleCounts = new Map<string, number>();
  for (const ev of rec.evidence) {
    const key = (ev.title ?? '').toLowerCase().trim();
    titleCounts.set(key, (titleCounts.get(key) ?? 0) + 1);
  }
  let duplicateEvidenceCount = 0;
  for (const count of titleCounts.values()) {
    if (count > 1) duplicateEvidenceCount += count - 1;
  }
  const uniqueEvidenceCount = totalEvidenceCount - duplicateEvidenceCount;
  const duplicateRatio = totalEvidenceCount > 0 ? duplicateEvidenceCount / totalEvidenceCount : 0;
  const hasDuplicateWarning = duplicateRatio > 0.2;

  // --- Source reliability: find primary contributing sources ---
  const evidenceSources = new Map<string, number>();
  for (const ev of rec.evidence) {
    const src = ev.source_type ?? ev.publisher ?? 'unknown';
    evidenceSources.set(src, (evidenceSources.get(src) ?? 0) + ev.weight);
  }
  // Sort by total weight descending to find primary source
  const sortedSources = [...evidenceSources.entries()].sort((a, b) => b[1] - a[1]);
  const primarySourceType = sortedSources[0]?.[0];

  // Look up source reliability from attribution data
  const primarySourceAttribution = sourcesData?.sources?.find(
    (s) => s.source_type === primarySourceType || s.source === primarySourceType,
  );
  // Source reliability is approximated from win_rate via Bayesian shrinkage
  // The attribution data has win_rate which is the observed metric
  const primarySourceWinRate = primarySourceAttribution?.win_rate;
  // Bayesian shrinkage: reliability = 0.5 + (n/(n+30)) * (win_rate - 0.5)
  const primarySourceCount = primarySourceAttribution?.prediction_count ?? 0;
  const primarySourceReliability =
    primarySourceWinRate != null
      ? 0.5 + (primarySourceCount / (primarySourceCount + 30)) * (primarySourceWinRate - 0.5)
      : undefined;
  const hasLowReliabilityWarning =
    primarySourceReliability != null && primarySourceReliability < 0.4;

  // --- Gate status ---
  const gateStatus = gateData?.gate_status as {
    passed?: boolean;
    reason?: string;
    threshold_results?: Array<{ name: string; threshold: number; actual: number; passed: boolean }>;
  } | null;

  return (
    <div className="space-y-6">
      <div className="flex items-center gap-3">
        <h1 className="text-xl font-semibold text-gray-100">{rec.ticker}</h1>
        <StatusBadge status={rec.action} />
        <StatusBadge status={rec.mode} />
      </div>

      <Card>
        <dl className="grid grid-cols-2 gap-x-8 gap-y-3 text-sm sm:grid-cols-4">
          <div><dt className="text-gray-500">Confidence</dt><dd><ConfidenceBar value={rec.confidence} /></dd></div>
          <div><dt className="text-gray-500">Horizon</dt><dd className="text-gray-200">{rec.time_horizon}</dd></div>
          <div><dt className="text-gray-500">Risk</dt><dd><StatusBadge status={rec.risk_classification} /></dd></div>
          <div><dt className="text-gray-500">Generated</dt><dd className="text-gray-300">{new Date(rec.generated_at).toLocaleString()}</dd></div>
          <div><dt className="text-gray-500">Portfolio %</dt><dd className="text-gray-200">{rec.portfolio_pct != null ? `${(rec.portfolio_pct * 100).toFixed(1)}%` : '—'}</dd></div>
          <div><dt className="text-gray-500">Max Loss %</dt><dd className="text-gray-200">{rec.max_loss_pct != null ? `${(rec.max_loss_pct * 100).toFixed(2)}%` : '—'}</dd></div>
          <div><dt className="text-gray-500">Model</dt><dd className="text-xs text-gray-400">{rec.model_version ?? '—'}</dd></div>
        </dl>
      </Card>

      {/* Validation Context Card — Requirements 13.1–13.7 */}
      <Card>
        <h2 className="mb-3 text-sm font-medium text-gray-400">Validation Context</h2>
        <dl className="grid grid-cols-2 gap-x-8 gap-y-3 text-sm sm:grid-cols-3">
          {/* 13.1: Original confidence alongside calibrated confidence */}
          <div>
            <dt className="text-gray-500">Original Confidence</dt>
            <dd className="text-gray-200">{(rec.confidence * 100).toFixed(1)}%</dd>
          </div>
          <div>
            <dt className="text-gray-500">Calibrated Confidence</dt>
            <dd className="text-gray-200">
              {historicalWinRate != null
                ? `${(historicalWinRate * 100).toFixed(1)}%`
                : 'N/A'}
            </dd>
          </div>

          {/* 13.2: Historical win rate for similar confidence levels */}
          <div>
            <dt className="text-gray-500">Historical Win Rate</dt>
            <dd className="text-gray-200">
              {historicalWinRate != null ? (
                <span>
                  {(historicalWinRate * 100).toFixed(1)}%
                  {calibratedBucket && (
                    <span className="ml-1 text-xs text-gray-500">
                      ({calibratedBucket.prediction_count} predictions)
                    </span>
                  )}
                </span>
              ) : (
                'N/A'
              )}
            </dd>
          </div>

          {/* 13.3: Evidence count, unique evidence count, duplicate evidence count */}
          <div>
            <dt className="text-gray-500">Evidence Count</dt>
            <dd className="text-gray-200">{totalEvidenceCount}</dd>
          </div>
          <div>
            <dt className="text-gray-500">Unique Evidence</dt>
            <dd className="text-gray-200">{uniqueEvidenceCount}</dd>
          </div>
          <div>
            <dt className="flex items-center gap-1 text-gray-500">
              Duplicate Evidence
              {/* 13.6: Warning badge when duplicate evidence count > 20% of total */}
              {hasDuplicateWarning && (
                <span
                  className="inline-flex items-center gap-0.5 rounded-full border border-yellow-700/50 bg-yellow-900/40 px-1.5 py-0.5 text-[10px] font-medium text-yellow-400"
                  title="Duplicate evidence exceeds 20% of total — potential evidence inflation"
                >
                  <AlertTriangle size={10} />
                  &gt;20%
                </span>
              )}
            </dt>
            <dd className="text-gray-200">
              {duplicateEvidenceCount}
              {totalEvidenceCount > 0 && (
                <span className="ml-1 text-xs text-gray-500">
                  ({(duplicateRatio * 100).toFixed(0)}%)
                </span>
              )}
            </dd>
          </div>

          {/* 13.4: Source reliability indicator */}
          <div>
            <dt className="flex items-center gap-1 text-gray-500">
              Primary Source Reliability
              {/* 13.7: Warning badge when primary source reliability < 0.4 */}
              {hasLowReliabilityWarning && (
                <span
                  className="inline-flex items-center gap-0.5 rounded-full border border-red-700/50 bg-red-900/40 px-1.5 py-0.5 text-[10px] font-medium text-red-400"
                  title="Primary source reliability is below 0.4 — low or unknown reliability"
                >
                  <AlertTriangle size={10} />
                  Low
                </span>
              )}
            </dt>
            <dd className="text-gray-200">
              {primarySourceReliability != null ? (
                <span>
                  {primarySourceReliability.toFixed(3)}
                  {primarySourceType && (
                    <span className="ml-1 text-xs text-gray-500">({primarySourceType})</span>
                  )}
                </span>
              ) : (
                'N/A'
              )}
            </dd>
          </div>

          {/* 13.5: Live eligibility status with reason */}
          <div className="col-span-2">
            <dt className="text-gray-500">Live Eligibility</dt>
            <dd>
              {gateStatus != null ? (
                <div className="flex items-center gap-2">
                  {gateStatus.passed ? (
                    <span className="inline-flex items-center gap-1 text-green-400">
                      <ShieldCheck size={14} />
                      Gate Passed
                    </span>
                  ) : (
                    <span className="inline-flex items-center gap-1 text-red-400">
                      <ShieldX size={14} />
                      Gate Failed
                    </span>
                  )}
                  {gateStatus.reason && (
                    <span className="text-xs text-gray-500">{gateStatus.reason}</span>
                  )}
                </div>
              ) : (
                <span className="inline-flex items-center gap-1 text-gray-500">
                  <Info size={14} />
                  N/A — no gate evaluation available
                </span>
              )}
            </dd>
          </div>
        </dl>
      </Card>

      {rec.thesis && (
        <Card>
          <h2 className="mb-2 text-sm font-medium text-gray-400">Thesis</h2>
          <p className="text-sm text-gray-200">{rec.thesis}</p>
        </Card>
      )}

      {rec.invalidation_conditions && rec.invalidation_conditions.length > 0 && (
        <Card>
          <h2 className="mb-2 text-sm font-medium text-gray-400">Invalidation Conditions</h2>
          <ul className="ml-4 list-disc text-sm text-yellow-400">
            {rec.invalidation_conditions.map((c, i) => <li key={i}>{c}</li>)}
          </ul>
        </Card>
      )}

      {/* Risk Evaluation */}
      {rec.risk_evaluation && (
        <Card>
          <h2 className="mb-2 text-sm font-medium text-gray-400">Risk Evaluation</h2>
          <div className="flex items-center gap-4 text-sm">
            <StatusBadge status={rec.risk_evaluation.eligible ? 'approved' : 'rejected'} />
            <span className="text-gray-400">Allowed mode: {rec.risk_evaluation.allowed_mode}</span>
          </div>
          {rec.risk_evaluation.rejection_reasons && rec.risk_evaluation.rejection_reasons.length > 0 && (
            <ul className="mt-2 ml-4 list-disc text-sm text-red-400">
              {rec.risk_evaluation.rejection_reasons.map((r, i) => <li key={i}>{r}</li>)}
            </ul>
          )}
        </Card>
      )}

      {/* Evidence */}
      <Card>
        <h2 className="mb-3 text-sm font-medium text-gray-400">Evidence ({rec.evidence.length})</h2>
        {rec.evidence.length === 0 ? (
          <p className="text-sm text-gray-500">No evidence linked</p>
        ) : (
          <div className="space-y-2">
            {rec.evidence.map((ev) => {
              const isMacro = ev.document_type === 'macro_event' || ev.evidence_type === 'macro_event';
              return (
                <div key={ev.id} className={`rounded-lg border p-3 ${isMacro ? 'border-purple-700/50 bg-purple-900/10' : 'border-surface-700 bg-surface-950'}`}>
                  <div className="flex items-center justify-between">
                    <div className="flex items-center gap-2">
                      {isMacro && (
                        <Link
                          to="/macro/events/$id"
                          params={{ id: ev.document_id }}
                          className="rounded bg-purple-900/40 border border-purple-700/50 px-1.5 py-0.5 text-[10px] font-medium text-purple-400 hover:text-purple-300"
                          onClick={(e) => e.stopPropagation()}
                        >
                          MACRO ↗
                        </Link>
                      )}
                      <StatusBadge status={ev.evidence_type} />
                      <span className="text-sm text-gray-200">{ev.title ?? 'Untitled'}</span>
                    </div>
                    <span className="font-mono text-xs text-gray-500">weight: {ev.weight.toFixed(3)}</span>
                  </div>
                  <div className="mt-1 flex gap-4 text-xs text-gray-500">
                    <span>{ev.document_type}</span>
                    <span>{ev.source_type}</span>
                    {ev.publisher && <span>{ev.publisher}</span>}
                    {ev.published_at && <span>{new Date(ev.published_at).toLocaleDateString()}</span>}
                  </div>
                </div>
              );
            })}
          </div>
        )}
      </Card>
    </div>
  );
}
