import { useMemo, useState } from 'react';
import { ChevronDown } from 'lucide-react';
import { VERIFY_TOLERANCE, verifyEpisode } from '@/lib/demo-kit/verify';
import type { AnyDemoModule } from '@/lib/demo-kit/registry';
import type { DemoEpisode } from '@/lib/demo-kit/types';
import { cn } from '@/lib/utils';
import { Chip } from './chrome';
import { DASH, formatDelta, formatNumber, formatOrDash } from './format';

export interface VerifyBadgeProps {
  demo: AnyDemoModule;
  episode: DemoEpisode;
  className?: string;
  /** Open the receipt on load. The sceptic we wrote this for opens it anyway. */
  defaultOpen?: boolean;
}

/**
 * The receipt.
 *
 * This object exists for one person: the engineer sitting next to the CEO who
 * assumes the numbers on a vendor's demo page are hard-coded. It re-runs the
 * recorded trace through the demo's own TypeScript grader, in the visitor's
 * browser, and prints the comparison — including the delta to seven decimals,
 * because a comparison without a delta is an assertion.
 *
 * It must be allowed to FAIL loudly. A badge that degrades to "verified" when
 * it could not check anything is worse than no badge: it teaches the sceptic
 * that the whole thing is decoration. The three states come straight from
 * `verifyEpisode`, and `unverifiable` is never dressed up as either of the
 * other two — it is a `?` on a plain ground, never a green tick.
 */
export function VerifyBadge({ demo, episode, className, defaultOpen = false }: VerifyBadgeProps) {
  const [open, setOpen] = useState(defaultOpen);
  const result = useMemo(() => verifyEpisode(demo, episode), [demo, episode]);

  if (result.status === 'unverifiable') {
    return (
      <section
        aria-label="Verification"
        className={cn('rounded-xl border border-border bg-surface-2 p-3 sm:p-4', className)}
      >
        <div className="flex flex-wrap items-center gap-2">
          <span
            aria-hidden="true"
            className="grid size-5 shrink-0 place-items-center rounded-sm border border-border-strong font-mono text-caption text-muted"
          >
            ?
          </span>
          <Chip variant="muted">Unverifiable in your browser</Chip>
        </div>
        <p className="mt-2 max-w-measure text-prose text-fg-2">
          {result.reason ?? 'This run cannot be re-computed here.'}
        </p>
        <p className="mt-2 font-mono text-caption text-muted">
          recomputed {DASH} · recorded {formatOrDash(result.recorded)} · Δ {DASH}
        </p>
      </section>
    );
  }

  const matched = result.status === 'match';

  return (
    <section
      aria-label="Verification"
      className={cn(
        'overflow-hidden rounded-xl border',
        // Match: accent-subtle ground, accent-fg edge. Mismatch: danger-subtle
        // ground, danger edge — danger text on danger-subtle is 4.72 dark /
        // 5.66 light, the last ground the red is allowed on.
        matched ? 'border-accent-fg bg-accent-subtle' : 'border-danger bg-danger-subtle',
        className,
      )}
    >
      <div className="p-3 sm:p-4">
        <div className="flex flex-wrap items-center gap-2">
          {matched ? (
            <Chip variant="positive" className="border-accent-fg">
              ✓ Verified in your browser
            </Chip>
          ) : (
            <Chip variant="danger" className="border-danger">
              ✗{' '}
              {result.culprit
                ? `Mismatch on "${result.culprit.label}"`
                : 'Mismatch against the recorded score'}
            </Chip>
          )}
        </div>
        <p className="mt-2 max-w-measure text-prose text-fg-2">
          {matched
            ? 'Every move in this run was re-played through the TypeScript engine on this page and re-scored. The recorded number and the recomputed one agree.'
            : 'The browser re-run disagrees with the published number. Trust the source in the repository, not this page.'}
        </p>
        <p className={cn('mt-2 font-mono text-caption', matched ? 'text-fg-2' : 'text-danger')}>
          recomputed {formatOrDash(result.recomputed)} · recorded {formatOrDash(result.recorded)} ·
          Δ {result.delta === null ? DASH : formatDelta(result.delta)}
        </p>
      </div>

      <button
        type="button"
        onClick={() => setOpen((was) => !was)}
        aria-expanded={open}
        className="tap flex w-full items-center gap-1.5 border-t border-border bg-surface px-3 text-left text-small font-medium text-muted transition-colors duration-1 ease-enter hover:bg-surface-2 hover:text-fg"
      >
        <ChevronDown
          className={cn('size-4 text-border-strong transition-transform duration-2 ease-enter', open && 'rotate-180')}
          aria-hidden="true"
        />
        {open ? 'Hide the component-by-component receipt' : 'Show the component-by-component receipt'}
      </button>

      {open ? (
        <div className="border-t border-border bg-surface">
          <div className="overflow-x-auto">
            <table className="w-full border-collapse font-mono text-caption">
              <thead>
                <tr className="bg-surface-3 text-left text-label uppercase tracking-label text-muted">
                  <th scope="col" className="px-3 py-1.5 font-medium">
                    Component
                  </th>
                  <th scope="col" className="px-2 py-1.5 text-right font-medium">
                    Recorded
                  </th>
                  <th scope="col" className="px-2 py-1.5 text-right font-medium">
                    Recomputed
                  </th>
                  <th scope="col" className="px-3 py-1.5 text-right font-medium">
                    Δ
                  </th>
                </tr>
              </thead>
              <tbody className="divide-y divide-border">
                {result.components.map((row) => {
                  const bad = row.delta !== null && Math.abs(row.delta) > VERIFY_TOLERANCE;
                  return (
                    <tr key={row.key} className={cn(bad && 'bg-danger-subtle')}>
                      <th scope="row" className="whitespace-nowrap px-3 py-1.5 text-left font-normal text-fg">
                        {row.label}
                      </th>
                      <td className="px-2 py-1.5 text-right text-fg">
                        {row.recorded === null ? DASH : formatNumber(row.recorded, 6)}
                      </td>
                      <td className="px-2 py-1.5 text-right text-fg">
                        {row.recomputed === null ? DASH : formatNumber(row.recomputed, 6)}
                      </td>
                      <td className={cn('px-3 py-1.5 text-right', bad ? 'text-danger' : 'text-muted')}>
                        {/* An em dash, not 0.0000000: one side was never scored,
                            so there is no difference to report. */}
                        {row.delta === null ? DASH : formatDelta(row.delta)}
                      </td>
                    </tr>
                  );
                })}
              </tbody>
            </table>
          </div>
          <p className="max-w-measure-wide px-3 py-2 text-small text-muted">
            Tolerance {VERIFY_TOLERANCE.toExponential()}. The recorded numbers came out of Python
            and these came out of JavaScript; both are IEEE-754 doubles summing the same terms in
            a different order, so the comparison is made within a tolerance rather than demanding
            bit-identical floats.
          </p>
        </div>
      ) : null}
    </section>
  );
}
