import type { ButtonHTMLAttributes, ReactNode } from 'react';
import { CheckIcon, LockIcon, XIcon } from '@/components/ui/icons';
import { cn } from '@/lib/cn';
import s from './game.module.css';

/**
 * idle      answerable
 * picked    this player's locked-in answer (before reveal)
 * dimmed    another option after the player picked, or while answers are locked
 * removed   taken away by Second Chance
 * correct   the revealed correct answer
 * incorrect the player's wrong pick, after reveal
 * faded     any other option after reveal
 */
export type AnswerState = 'idle' | 'picked' | 'dimmed' | 'removed' | 'correct' | 'incorrect' | 'faded';

export interface AnswerButtonProps extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, 'children'> {
  letter: string;
  text: string;
  state?: AnswerState;
  /** Share of players who picked this option (0-1), shown after reveal. */
  share?: number | null;
  /** The pick is on its way to the server (shimmer). */
  sending?: boolean;
  /** Render as a static row instead of a button (TV, spectators). */
  static?: boolean;
  size?: 'phone' | 'tv';
}

const stateClass: Record<AnswerState, string> = {
  idle: 'border-line-strong bg-raised hover:border-violet-soft hover:bg-raised-hover motion-safe:active:scale-[0.98]',
  picked: 'border-violet bg-violet/30 shadow-glow-violet',
  dimmed: 'border-line bg-raised/60 text-muted',
  removed: 'border-line/60 bg-night/40 text-subtle',
  correct: 'border-lime bg-lime/15 shadow-glow-lime',
  incorrect: 'border-danger bg-danger/15',
  faded: 'border-line bg-raised/50 text-muted',
};

const badgeClass: Record<AnswerState, string> = {
  idle: 'bg-white/10 text-fg',
  picked: 'bg-violet text-white',
  dimmed: 'bg-white/5 text-muted',
  removed: 'bg-white/5 text-subtle',
  correct: 'bg-lime text-on-bright',
  incorrect: 'bg-danger text-on-bright',
  faded: 'bg-white/5 text-muted',
};

/** Text + icon cue for each state so meaning never rides on colour alone. */
function StateTag({ state }: { state: AnswerState }): ReactNode {
  switch (state) {
    case 'picked':
      return (
        <span className="ml-auto inline-flex shrink-0 items-center gap-1 text-xs font-bold tracking-[0.1em] text-violet-soft uppercase">
          <LockIcon className="size-4" /> Locked in
        </span>
      );
    case 'correct':
      return (
        <span className="ml-auto inline-flex shrink-0 items-center gap-1 text-xs font-bold tracking-[0.1em] text-lime-soft uppercase">
          <CheckIcon className="size-4" strokeWidth={3} /> Correct
        </span>
      );
    case 'incorrect':
      return (
        <span className="ml-auto inline-flex shrink-0 items-center gap-1 text-xs font-bold tracking-[0.1em] text-danger-soft uppercase">
          <XIcon className="size-4" strokeWidth={3} /> Your pick
        </span>
      );
    case 'removed':
      return <span className="ml-auto shrink-0 text-xs font-bold tracking-[0.1em] text-subtle uppercase">Removed</span>;
    default:
      return null;
  }
}

/**
 * One answer option. Full width, at least 56 px tall on phones (thumb target), letter badge + text,
 * optional distribution bar after the reveal.
 */
export function AnswerButton({
  letter,
  text,
  state = 'idle',
  share = null,
  sending = false,
  static: isStatic = false,
  size = 'phone',
  className,
  disabled,
  ...rest
}: AnswerButtonProps) {
  const pct = share === null ? null : Math.round(Math.max(0, Math.min(1, share)) * 100);
  const body = (
    <>
      {pct !== null && (
        <span
          aria-hidden="true"
          className={cn(
            'absolute inset-y-0 left-0 rounded-[inherit]',
            state === 'correct' ? 'bg-lime/20' : state === 'incorrect' ? 'bg-danger/20' : 'bg-white/[0.06]',
          )}
          style={{ width: `${pct}%` }}
        />
      )}
      {sending && <span aria-hidden="true" className={s.shimmer} />}
      <span
        aria-hidden="true"
        className={cn(
          'relative grid shrink-0 place-items-center rounded-lg font-display font-bold',
          size === 'tv' ? 'size-14 text-3xl' : 'size-9 text-base',
          badgeClass[state],
        )}
      >
        {letter}
      </span>
      <span className={cn('relative min-w-0 flex-1 text-left leading-snug', state === 'removed' && 'line-through decoration-2')}>
        <span className="sr-only">{`${letter}: `}</span>
        {text}
      </span>
      <span className="relative flex shrink-0 items-center gap-2">
        {pct !== null && <span className="num text-sm font-bold text-muted">{pct}%</span>}
        <StateTag state={state} />
      </span>
    </>
  );

  const shared = cn(
    'relative flex w-full items-center gap-3 overflow-hidden rounded-2xl border-2 text-left font-semibold',
    'transition-[transform,background-color,border-color,box-shadow,opacity] duration-150',
    size === 'tv' ? 'min-h-24 px-6 py-4 text-3xl' : 'min-h-14 px-3 py-2.5 text-base sm:text-lg',
    stateClass[state],
    className,
  );

  if (isStatic) return <div className={shared}>{body}</div>;
  return (
    <button type="button" className={cn(shared, 'select-none disabled:cursor-default')} disabled={disabled} {...rest}>
      {body}
    </button>
  );
}
