import { useState, useEffect } from "react";
import type { CharacterSpell, Spell, SpellCastResult } from "../types.js";
import { getSpells, addCharacterSpell, removeCharacterSpell, castSpell } from "../api.js";
import styles from "./SpellList.module.css";

interface SpellListProps {
  characterId: number;
  characterClass: string;
  spells: CharacterSpell[];
  mode: "view" | "edit";
  canEdit: boolean;
  onSpellAdded: (spell: CharacterSpell) => void;
  onSpellRemoved: (spellId: number) => void;
  onSpellCast: (result: SpellCastResult, spellName: string) => void;
  onSpellsUpdated: (spells: CharacterSpell[]) => void;
}

export default function SpellList({
  characterId,
  characterClass,
  spells,
  mode,
  canEdit,
  onSpellAdded,
  onSpellRemoved,
  onSpellCast,
  onSpellsUpdated,
}: SpellListProps) {
  const [allSpells, setAllSpells] = useState<Spell[]>([]);
  const [showPicker, setShowPicker] = useState(false);
  const [casting, setCasting] = useState<number | null>(null);

  const isCaster = ["Wizard", "Priest"].includes(characterClass);

  useEffect(() => {
    if (!isCaster) return;
    const spellClass = characterClass.toLowerCase();
    getSpells(spellClass).then(setAllSpells);
  }, [characterClass, isCaster]);

  if (!isCaster) return null;

  const knownIds = new Set(spells.map((s) => s.spell_id));
  const availableToAdd = allSpells.filter((s) => !knownIds.has(s.id));

  const byTier: Record<number, CharacterSpell[]> = {};
  for (const s of spells) {
    byTier[s.tier] = byTier[s.tier] ?? [];
    byTier[s.tier].push(s);
  }

  async function handleCast(spell: CharacterSpell) {
    setCasting(spell.spell_id);
    try {
      const result = await castSpell(characterId, spell.spell_id);
      onSpellCast(result, spell.name);
      const exhausted = result.result === "success" || result.result === "crit_success" ? 0 : 1;
      onSpellsUpdated(
        spells.map((s) => (s.spell_id === spell.spell_id ? { ...s, exhausted } : s))
      );
    } catch (err) {
      console.error("Cast failed", err);
    } finally {
      setCasting(null);
    }
  }

  async function handleRemove(spellId: number) {
    await removeCharacterSpell(characterId, spellId);
    onSpellRemoved(spellId);
  }

  async function handleAdd(spell: Spell) {
    const cs = await addCharacterSpell(characterId, spell.id);
    onSpellAdded(cs);
    setShowPicker(false);
  }

  return (
    <div className={styles.container}>
      <div className={styles.header}>
        <span className={styles.sectionTitle}>Spells</span>
        {canEdit && mode === "edit" && (
          <button className={styles.addBtn} onClick={() => setShowPicker((p) => !p)}>
            {showPicker ? "Cancel" : "+ Add Spell"}
          </button>
        )}
      </div>

      {showPicker && (
        <div className={styles.picker}>
          {availableToAdd.length === 0 && (
            <p className={styles.empty}>All available spells known.</p>
          )}
          {availableToAdd.map((s) => (
            <button key={s.id} className={styles.pickerItem} onClick={() => handleAdd(s)}>
              <span className={styles.tierBadge}>T{s.tier}</span>
              <span className={styles.pickerName}>{s.name}</span>
              {s.is_focus ? <span className={styles.focusBadge}>Focus</span> : null}
            </button>
          ))}
        </div>
      )}

      {spells.length === 0 && !showPicker && (
        <p className={styles.empty}>
          No spells known.{canEdit && mode === "edit" ? " Add some above." : ""}
        </p>
      )}

      {Object.entries(byTier)
        .sort(([a], [b]) => Number(a) - Number(b))
        .map(([tier, tierSpells]) => (
          <div key={tier} className={styles.tierGroup}>
            <div className={styles.tierLabel}>Tier {tier}</div>
            {tierSpells.map((s) => (
              <div
                key={s.id}
                className={[
                  styles.spell,
                  s.exhausted ? styles.exhausted : "",
                  s.focus_active ? styles.focusing : "",
                ]
                  .filter(Boolean)
                  .join(" ")}
              >
                <div className={styles.spellMain}>
                  <span className={styles.spellName}>{s.name}</span>
                  {s.focus_active ? (
                    <span className={styles.focusActive}>&#9679; Focusing</span>
                  ) : null}
                  {s.exhausted ? (
                    <span className={styles.exhaustedLabel}>Exhausted</span>
                  ) : null}
                  {s.locked_until ? (
                    <span className={styles.lockedLabel}>Locked</span>
                  ) : null}
                </div>
                <div className={styles.spellMeta}>
                  {s.duration} &middot; {s.range}
                </div>
                <div className={styles.spellDesc}>{s.description}</div>
                <div className={styles.spellActions}>
                  {canEdit && (
                    <button
                      className={styles.castBtn}
                      disabled={!!s.exhausted || !!s.locked_until || casting === s.spell_id}
                      onClick={() => handleCast(s)}
                    >
                      {casting === s.spell_id ? "Rolling\u2026" : "Cast"}
                    </button>
                  )}
                  {canEdit && mode === "edit" && (
                    <button
                      className={styles.removeBtn}
                      onClick={() => handleRemove(s.spell_id)}
                    >
                      &#10005;
                    </button>
                  )}
                </div>
              </div>
            ))}
          </div>
        ))}
    </div>
  );
}
