import type { FactBand, FactStatus } from '@pig/core';
import { Clock3, ExternalLink, Link2, ScanSearch } from 'lucide-react';
import type { ReactNode } from 'react';
import { Badge } from '@/components/ui';
import {
  Popover,
  PopoverContent,
  PopoverTrigger,
} from '@/components/ui/popover';
import { Separator } from '@/components/ui/separator';
import { cn } from '@/lib/utils';

export interface SourcedFact {
  id: string;
  field: string;
  value: string;
  score: string | number;
  band: FactBand;
  status: FactStatus;
  evidence: Record<string, unknown> | null;
  sourceUrl: string | null;
  method: string | null;
  observedAt: string;
}

interface SourcedValueProps {
  value: ReactNode;
  fact: SourcedFact;
  className?: string;
}

const BAND_TONE = {
  verified: 'positive',
  probable: 'info',
  possible: 'warning',
} as const;

function safeSourceUrl(value: string | null): string | null {
  if (!value) return null;
  try {
    const url = new URL(value);
    return url.protocol === 'https:' || url.protocol === 'http:' ? url.href : null;
  } catch {
    return null;
  }
}

function evidenceSummary(evidence: Record<string, unknown> | null): string | null {
  if (!evidence) return null;
  for (const key of ['excerpt', 'quote', 'summary', 'snippet', 'reason']) {
    const value = evidence[key];
    if (typeof value === 'string' && value.trim()) return value.trim();
  }
  const firstText = Object.values(evidence).find(
    (value): value is string => typeof value === 'string' && Boolean(value.trim()),
  );
  return firstText?.trim() ?? null;
}

function humanise(value: string): string {
  return value.replaceAll('_', ' ').replace(/\b\w/g, (letter) => letter.toUpperCase());
}

export function SourcedValue({ value, fact, className }: SourcedValueProps) {
  const sourceUrl = safeSourceUrl(fact.sourceUrl);
  const summary = evidenceSummary(fact.evidence);
  const score = Number(fact.score);
  const confidence = Number.isFinite(score) ? `${Math.round(score * 100)}%` : 'Not scored';
  const observedDate = new Date(fact.observedAt);
  const observedLabel = Number.isNaN(observedDate.getTime()) ? 'Observation date unavailable' : observedDate.toLocaleDateString(undefined, { dateStyle: 'medium' });
  const sourceHost = sourceUrl ? new URL(sourceUrl).hostname.replace(/^www\./, '') : null;

  return (
    <span className={cn('inline-flex min-w-0 items-center gap-1.5', className)}>
      <span className="min-w-0 break-words font-medium text-fg">{value}</span>
      <Popover>
        <PopoverTrigger asChild>
          <button
            type="button"
            className="tap -my-2 inline-flex size-11 shrink-0 items-center justify-center rounded-md text-accent-fg hover:bg-accent-subtle"
            aria-label={`View ${fact.band} evidence for ${fact.field}`}
          >
            <Link2 className="size-3.5" aria-hidden />
          </button>
        </PopoverTrigger>
        <PopoverContent
          align="start"
          className="w-[min(22rem,calc(100vw-2rem))] border-border bg-surface text-fg"
        >
          <div className="flex flex-col gap-3">
            <div className="flex min-w-0 items-start justify-between gap-3">
              <div className="min-w-0">
                <p className="text-xs font-medium uppercase tracking-wide text-muted">
                  Source evidence · {humanise(fact.field)}
                </p>
                <p className="mt-1 break-words text-sm font-medium">{fact.value}</p>
              </div>
              <Badge tone={BAND_TONE[fact.band]}>{confidence}</Badge>
            </div>
            <Separator />
            <div className="flex gap-2 text-sm">
              <ScanSearch className="mt-0.5 size-4 shrink-0 text-muted" aria-hidden />
              <div className="min-w-0">
                <p className="font-medium">Evidence</p>
                <p className="mt-0.5 break-words text-muted">
                  {summary ?? 'No evidence excerpt was recorded.'}
                </p>
              </div>
            </div>
            <div className="flex flex-wrap items-center gap-2 text-xs text-muted">
              <Badge tone="neutral">{humanise(fact.band)}</Badge>
              <Badge tone="neutral">{humanise(fact.status)}</Badge>
              {fact.method ? <span>via {humanise(fact.method)}</span> : null}
            </div>
            <div className="flex items-center gap-2 text-xs text-muted"><Clock3 className="size-3.5 shrink-0" aria-hidden /><span>Observed <time dateTime={fact.observedAt}>{observedLabel}</time></span></div>
            {sourceUrl ? (
              <a
                href={sourceUrl}
                target="_blank"
                rel="noreferrer"
                className="inline-flex min-h-11 items-center gap-2 break-all text-sm font-medium text-accent-fg hover:underline"
              >
                Open source{sourceHost ? ` · ${sourceHost}` : ''}
                <ExternalLink className="size-3.5 shrink-0" aria-hidden />
              </a>
            ) : null}
          </div>
        </PopoverContent>
      </Popover>
    </span>
  );
}
