import { useState } from 'react';
import type { AbilityKey, AbilityScores } from '@/lib/rules';
import { ABILITY_ABBR, abilityModifier } from '@/lib/rules';
import { createRng } from '@/lib/rng';
import {
  STANDARD_ARRAY,
  rollAbilityScores,
  pointBuyRemaining,
  POINT_BUY_MIN,
  POINT_BUY_MAX,
} from '@/lib/rules/abilityGen';
import { formatModifier } from '@/lib/format';
import { Modal } from '@/components/ui/Modal';
import { Button } from '@/components/ui/Button';
import { Select } from '@/components/ui/Input';
import { NumberField } from '@/components/ui/NumberField';
import { cn } from '@/lib/cn';

const ABILITIES: AbilityKey[] = ['str', 'dex', 'con', 'int', 'wis', 'cha'];
type Method = 'standard' | 'roll' | 'pointbuy';

export function AbilityGenModal({ onApply, onClose }: { onApply: (scores: AbilityScores) => void; onClose: () => void }) {
  const [method, setMethod] = useState<Method>('standard');
  const [pool, setPool] = useState<number[]>([...STANDARD_ARRAY]);
  // assignment[i] = pool index assigned to ABILITIES[i], or -1
  const [assignment, setAssignment] = useState<number[]>(ABILITIES.map((_, i) => i));
  const [pb, setPb] = useState<number[]>([8, 8, 8, 8, 8, 8]);

  const chooseMethod = (m: Method) => {
    setMethod(m);
    if (m === 'standard') { setPool([...STANDARD_ARRAY]); setAssignment(ABILITIES.map((_, i) => i)); }
    if (m === 'roll') { const p = rollAbilityScores(createRng()); setPool(p); setAssignment(ABILITIES.map((_, i) => i)); }
  };

  const reroll = () => { setPool(rollAbilityScores(createRng())); setAssignment(ABILITIES.map((_, i) => i)); };

  const usesPool = method === 'standard' || method === 'roll';
  const remaining = pointBuyRemaining(pb);

  const toScores = (): AbilityScores => {
    const out = {} as AbilityScores;
    ABILITIES.forEach((a, i) => {
      out[a] = usesPool ? (pool[assignment[i]!] ?? 10) : pb[i]!;
    });
    return out;
  };

  const poolValid = !usesPool || new Set(assignment).size === ABILITIES.length;
  const pbValid = method !== 'pointbuy' || remaining >= 0;
  const valid = poolValid && pbValid;

  return (
    <Modal
      open
      onClose={onClose}
      title="Generate ability scores"
      className="max-w-xl"
      footer={
        <>
          <Button variant="ghost" onClick={onClose}>Cancel</Button>
          <Button variant="primary" disabled={!valid} onClick={() => { onApply(toScores()); onClose(); }}>Apply</Button>
        </>
      }
    >
      <div className="mb-4 flex gap-1">
        {([['standard', 'Standard array'], ['pointbuy', 'Point buy'], ['roll', '4d6 drop lowest']] as const).map(([m, label]) => (
          <button
            key={m}
            onClick={() => chooseMethod(m)}
            className={cn('rounded-md px-3 py-1.5 text-sm', method === m ? 'bg-accent text-accent-ink' : 'bg-elevated text-muted hover:text-ink')}
          >
            {label}
          </button>
        ))}
      </div>

      {method === 'roll' && (
        <Button size="sm" variant="secondary" className="mb-3" onClick={reroll}>↻ Reroll</Button>
      )}
      {method === 'pointbuy' && (
        <p className={cn('mb-3 text-sm', remaining < 0 ? 'text-danger' : 'text-muted')}>
          Points remaining: <span className="font-semibold text-ink">{remaining}</span> / 27
        </p>
      )}
      {usesPool && !poolValid && <p className="mb-3 text-sm text-warning">Assign each value to a different ability.</p>}

      <div className="grid grid-cols-2 gap-3 sm:grid-cols-3">
        {ABILITIES.map((a, i) => {
          const value = usesPool ? (pool[assignment[i]!] ?? 0) : pb[i]!;
          return (
            <div key={a} className="rounded-lg border border-line bg-surface p-3 text-center">
              <div className="text-xs font-semibold uppercase tracking-wide text-muted">{ABILITY_ABBR[a]}</div>
              {usesPool ? (
                <Select
                  className="mt-1"
                  aria-label={`${ABILITY_ABBR[a]} value`}
                  value={assignment[i]}
                  onChange={(e) => setAssignment((prev) => prev.map((v, j) => (j === i ? Number(e.target.value) : v)))}
                >
                  {pool.map((p, idx) => (
                    <option key={idx} value={idx} disabled={assignment.includes(idx) && assignment[i] !== idx}>
                      {p}
                    </option>
                  ))}
                </Select>
              ) : (
                <NumberField
                  className="mt-1"
                  value={pb[i]!}
                  min={POINT_BUY_MIN}
                  max={POINT_BUY_MAX}
                  aria-label={`${ABILITY_ABBR[a]} score`}
                  onChange={(v) => setPb((prev) => prev.map((x, j) => (j === i ? Math.max(POINT_BUY_MIN, Math.min(POINT_BUY_MAX, v)) : x)))}
                />
              )}
              <div className="mt-1 text-xs text-accent">{formatModifier(abilityModifier(value))}</div>
            </div>
          );
        })}
      </div>
    </Modal>
  );
}
