import type { ComponentType } from 'react';
import { Link } from 'react-router-dom';
import { ArrowRight } from 'lucide-react';
import type { DemoMeta } from '@/lib/demo-kit/types';
import { VERTICAL_LABELS } from '@/lib/demo-kit/registry';
import { Badge } from '@/components/ui/badge';
import { DemoIcon } from '@/components/site/DemoIcon';
import { cn } from '@/lib/utils';

export interface DemoCardProps<T> {
  meta: DemoMeta;
  /** Defaults to the canonical demo route. */
  href?: string;
  /**
   * The demo's OWN board, drawn compact, as the thumbnail. A screenshot would
   * go stale the first time the board changed and nobody would notice; this
   * cannot, because it is the same component the demo page renders.
   */
  Surface?: ComponentType<{ state: T; compact?: boolean }>;
  /** A representative state for the thumbnail — usually a solved board. */
  thumbnailState?: T;
  className?: string;
}

export function DemoCard<T>({ meta, href, Surface, thumbnailState, className }: DemoCardProps<T>) {
  const to = href ?? `/demos/${meta.slug}`;
  const isSpec = meta.status === 'spec';
  const showSurface = Surface !== undefined && thumbnailState !== undefined;

  return (
    <article
      className={cn(
        'card group relative flex flex-col overflow-hidden transition-colors duration-2 ease-enter hover:border-brand/40',
        className,
      )}
    >
      <div className="flex items-start gap-3 p-4 pb-3">
        <span className="grid size-10 shrink-0 place-items-center rounded-lg bg-accent-subtle text-accent-fg">
          <DemoIcon name={meta.icon} className="size-5" />
        </span>
        <div className="min-w-0 flex-1">
          <h3 className="text-base font-semibold leading-tight">
            {/* Stretched link: the whole card is the hit target, but there is
                still exactly ONE link in the accessibility tree for it. */}
            <Link to={to} className="after:absolute after:inset-0 after:content-['']">
              {meta.title}
            </Link>
          </h3>
          <p className="mt-0.5 text-sm leading-snug text-muted">{meta.tagline}</p>
        </div>
        {isSpec ? (
          <Badge variant="outline" className="shrink-0 uppercase tracking-wide">
            Spec
          </Badge>
        ) : null}
      </div>

      {showSurface ? (
        <div className="mx-4 overflow-hidden rounded-lg bg-surface-2 p-3">
          {/* Decorative: the title and tagline already name the demo, and a
              board with no run behind it is not information. */}
          <div aria-hidden="true">
            <Surface state={thumbnailState as T} compact />
          </div>
        </div>
      ) : null}

      <dl className="mt-3 flex flex-wrap gap-x-4 gap-y-1 px-4 text-xs">
        <div className="flex gap-1">
          <dt className="text-muted">For</dt>
          <dd className="font-medium">{meta.persona}</dd>
        </div>
        <div className="flex gap-1">
          <dt className="text-muted">Vertical</dt>
          <dd className="font-medium">{VERTICAL_LABELS[meta.vertical]}</dd>
        </div>
      </dl>

      <p className="mt-2 px-4 pb-4 text-xs leading-relaxed text-muted">
        <span className="font-medium text-fg">Reward: </span>
        {meta.rewardLine}
      </p>

      <p className="mt-auto flex items-center gap-1 border-t border-border px-4 py-2.5 text-sm font-medium text-accent-fg">
        {isSpec ? 'Read the specification' : 'Open the demo'}
        <ArrowRight
          className="size-4 transition-transform duration-2 ease-enter group-hover:translate-x-0.5"
          aria-hidden="true"
        />
      </p>
    </article>
  );
}
