import { useState } from 'react';
import { Sparkles, BrainCircuit } from 'lucide-react';
import { newId } from '@/lib/ids';
import { getSystem } from '@/lib/rules';
import type { AbilityKey, CharacterRulesInput, ProficiencyRank } from '@/lib/rules';
import { type SpellEntry, newSpellEntry } from '@/lib/schemas';
import { castSpell, dropConcentration } from '@/lib/mechanics';
import { formatModifier } from '@/lib/format';
import { Button } from '@/components/ui/Button';
import { Input, Select } from '@/components/ui/Input';
import { NumberField } from '@/components/ui/NumberField';
import { SheetSection, type SectionProps } from './common';

const CASTING_ABILITIES: { key: AbilityKey; label: string }[] = [
  { key: 'int', label: 'Intelligence' },
  { key: 'wis', label: 'Wisdom' },
  { key: 'cha', label: 'Charisma' },
];

export function SpellcastingSection({ c, update }: SectionProps) {
  const [spellName, setSpellName] = useState('');
  const [spellLevel, setSpellLevel] = useState(0);
  const sys = getSystem(c.system);
  const sc = c.spellcasting;

  const ability = c.spellcastingAbility;
  const rulesInput: CharacterRulesInput = {
    level: c.level,
    abilities: c.abilities,
    ...(c.spellcastingRank ? { spellcastingRank: c.spellcastingRank as ProficiencyRank } : {}),
  };
  const dc = ability ? sys.spellSaveDc?.(rulesInput, ability) : undefined;
  const atk = ability ? sys.spellAttackBonus(rulesInput, ability) : undefined;

  const setSlots = (slots: typeof sc.slots) => update({ spellcasting: { ...sc, slots } });
  const patchSlot = (level: number, p: Partial<(typeof sc.slots)[number]>) =>
    setSlots(sc.slots.map((s) => (s.level === level ? { ...s, ...p } : s)));
  const addSlotLevel = () => {
    const next = (sc.slots.at(-1)?.level ?? 0) + 1;
    if (next > 9) return;
    setSlots([...sc.slots, { level: next, max: 1, current: 1 }]);
  };

  const addSpell = () => {
    if (spellName.trim() === '') return;
    const entry: SpellEntry = newSpellEntry({ id: newId(), name: spellName.trim(), level: spellLevel });
    update({ spellcasting: { ...sc, spells: [...sc.spells, entry] } });
    setSpellName('');
  };
  const patchSpell = (id: string, p: Partial<SpellEntry>) =>
    update({ spellcasting: { ...sc, spells: sc.spells.map((s) => (s.id === id ? { ...s, ...p } : s)) } });
  const removeSpell = (id: string) =>
    update({ spellcasting: { ...sc, spells: sc.spells.filter((s) => s.id !== id) } });

  // Casting a spell enforces slot consumption + concentration via the kernel.
  const [castMsg, setCastMsg] = useState<{ text: string; ok: boolean } | null>(null);
  const cast = (id: string) => {
    const res = castSpell(c, id);
    if (res.ok) {
      update(res.patch);
      setCastMsg({ text: res.log.join(' '), ok: true });
    } else {
      setCastMsg({ text: res.reason, ok: false });
    }
  };

  const spellsByLevel = [...sc.spells].sort((a, b) => a.level - b.level || a.name.localeCompare(b.name));

  return (
    <SheetSection title="Spellcasting">
      <div className="mb-3 flex flex-wrap items-center gap-3">
        <label className="text-xs text-muted">
          Casting ability
          <Select
            className="ml-2 w-auto"
            value={ability ?? ''}
            onChange={(e) => update({ spellcastingAbility: (e.target.value || undefined) as typeof c.spellcastingAbility })}
          >
            <option value="">None</option>
            {CASTING_ABILITIES.map((a) => (
              <option key={a.key} value={a.key}>{a.label}</option>
            ))}
          </Select>
        </label>
        {ability && (
          <div className="flex gap-4 text-sm">
            <span className="text-muted">Spell DC <span className="font-display text-lg font-semibold text-accent">{dc}</span></span>
            <span className="text-muted">Attack <span className="font-display text-lg font-semibold text-accent">{atk !== undefined ? formatModifier(atk) : '—'}</span></span>
          </div>
        )}
      </div>

      {/* Concentration banner — enforced: one spell at a time. */}
      {c.concentration && (
        <div className="mb-3 flex items-center gap-2 rounded-md border border-accent/40 bg-accent/5 px-3 py-1.5 text-sm">
          <BrainCircuit size={15} className="shrink-0 text-accent" aria-hidden />
          <span className="text-ink">Concentrating on <span className="font-medium">{c.concentration.spellName}</span></span>
          <Button size="sm" variant="ghost" className="ml-auto" onClick={() => update(dropConcentration(c))}>Drop</Button>
        </div>
      )}
      {castMsg && (
        <p className={`mb-3 text-xs ${castMsg.ok ? 'text-success' : 'text-danger'}`} aria-live="polite">{castMsg.text}</p>
      )}

      {/* Spell slots */}
      <div className="mb-4">
        <div className="mb-1 flex items-center gap-2">
          <span className="text-xs font-semibold uppercase tracking-wide text-muted">Spell slots</span>
          <Button size="sm" variant="ghost" onClick={addSlotLevel}>+ slot level</Button>
        </div>
        {sc.slots.length === 0 ? (
          <p className="text-sm text-muted">No spell slots configured.</p>
        ) : (
          <div className="flex flex-wrap gap-2">
            {sc.slots.map((s) => (
              <div key={s.level} className="rounded-md border border-line bg-panel px-2 py-1 text-center">
                <div className="text-[10px] uppercase text-muted">Lv {s.level}</div>
                <div className="flex items-center gap-1">
                  <Button size="icon" variant="ghost" className="h-6 w-6" onClick={() => patchSlot(s.level, { current: Math.max(0, s.current - 1) })} aria-label={`Spend level ${s.level} slot`}>−</Button>
                  <span className="text-sm"><span className="font-medium text-ink">{s.current}</span>/<NumberField className="inline-block w-12" value={s.max} min={0} onChange={(v) => patchSlot(s.level, { max: v, current: Math.min(v, s.current) })} aria-label={`Level ${s.level} max slots`} /></span>
                  <Button size="icon" variant="ghost" className="h-6 w-6" onClick={() => patchSlot(s.level, { current: Math.min(s.max, s.current + 1) })} aria-label={`Regain level ${s.level} slot`}>+</Button>
                </div>
              </div>
            ))}
          </div>
        )}
      </div>

      {/* Spell list */}
      <div className="mb-2 flex items-end gap-2">
        <label className="flex-1 min-w-40 text-xs text-muted">
          Add spell
          <Input value={spellName} onChange={(e) => setSpellName(e.target.value)} onKeyDown={(e) => e.key === 'Enter' && addSpell()} placeholder="Fireball" />
        </label>
        <label className="text-xs text-muted">
          Level
          <Select className="w-20" value={spellLevel} onChange={(e) => setSpellLevel(Number(e.target.value))}>
            <option value={0}>Cantrip</option>
            {Array.from({ length: 9 }, (_, i) => i + 1).map((l) => (
              <option key={l} value={l}>{l}</option>
            ))}
          </Select>
        </label>
        <Button variant="primary" onClick={addSpell}>Add</Button>
      </div>
      {spellsByLevel.length === 0 ? (
        <p className="text-sm text-muted">No spells added.</p>
      ) : (
        <ul className="space-y-1">
          {spellsByLevel.map((s) => (
            <li key={s.id} className="flex items-center gap-2 rounded-md border border-line bg-panel px-3 py-1.5 text-sm">
              <span className="w-16 text-xs text-muted">{s.level === 0 ? 'Cantrip' : `Lv ${s.level}`}</span>
              <span className="flex-1 text-ink">
                {s.name}
                {s.concentration && <BrainCircuit size={12} className="ml-1 inline text-accent" aria-label="Concentration" />}
              </span>
              {s.level > 0 && (
                <label className="flex items-center gap-1 text-xs text-muted">
                  <input type="checkbox" checked={s.prepared} onChange={(e) => patchSpell(s.id, { prepared: e.target.checked })} />
                  Prepared
                </label>
              )}
              <Button size="sm" variant="ghost" onClick={() => cast(s.id)} aria-label={`Cast ${s.name}`}>
                <Sparkles size={13} aria-hidden /> Cast
              </Button>
              <Button size="icon" variant="ghost" className="text-danger" onClick={() => removeSpell(s.id)} aria-label={`Remove ${s.name}`}>✕</Button>
            </li>
          ))}
        </ul>
      )}
    </SheetSection>
  );
}
