-- Magic: The Gathering Card System
-- Run with: lake exe mtg

-- ANCHOR: mana_colors
inductive ManaColor where
  | white | blue | black | red | green | colorless
  deriving Repr, DecidableEq

structure ManaCost where
  white : Nat := 0
  blue : Nat := 0
  black : Nat := 0
  red : Nat := 0
  green : Nat := 0
  colorless : Nat := 0
  deriving Repr

def ManaCost.total (c : ManaCost) : Nat :=
  c.white + c.blue + c.black + c.red + c.green + c.colorless
-- ANCHOR_END: mana_colors

-- ANCHOR: mana_pool
structure ManaPool where
  white : Nat := 0
  blue : Nat := 0
  black : Nat := 0
  red : Nat := 0
  green : Nat := 0
  colorless : Nat := 0
  deriving Repr

def ManaPool.total (p : ManaPool) : Nat :=
  p.white + p.blue + p.black + p.red + p.green + p.colorless

def ManaPool.canAfford (pool : ManaPool) (cost : ManaCost) : Bool :=
  pool.white >= cost.white &&
  pool.blue >= cost.blue &&
  pool.black >= cost.black &&
  pool.red >= cost.red &&
  pool.green >= cost.green &&
  pool.total >= cost.total

def ManaPool.pay (pool : ManaPool) (cost : ManaCost) : Option ManaPool :=
  if pool.canAfford cost then
    some { white := pool.white - cost.white
           blue := pool.blue - cost.blue
           black := pool.black - cost.black
           red := pool.red - cost.red
           green := pool.green - cost.green
           colorless := pool.total - cost.total -
             (pool.white - cost.white) - (pool.blue - cost.blue) -
             (pool.black - cost.black) - (pool.red - cost.red) -
             (pool.green - cost.green) }
  else
    none
-- ANCHOR_END: mana_pool

-- ANCHOR: card_types
inductive CardType where
  | creature (power : Nat) (toughness : Nat)
  | instant
  | sorcery
  | enchantment
  | artifact
  deriving Repr

structure Card where
  name : String
  cost : ManaCost
  cardType : CardType
  deriving Repr
-- ANCHOR_END: card_types

-- ANCHOR: sample_cards
def goblinGuide : Card :=
  { name := "Goblin Guide"
    cost := { red := 1 }
    cardType := .creature 2 2 }

def searingSpear : Card :=
  { name := "Searing Spear"
    cost := { red := 1, colorless := 1 }
    cardType := .instant }

def dayOfJudgment : Card :=
  { name := "Day of Judgment"
    cost := { white := 2, colorless := 2 }
    cardType := .sorcery }

def swordOfFire : Card :=
  { name := "Sword of Fire and Ice"
    cost := { colorless := 3 }
    cardType := .artifact }

def graveTitan : Card :=
  { name := "Grave Titan"
    cost := { black := 2, colorless := 4 }
    cardType := .creature 6 6 }
-- ANCHOR_END: sample_cards

-- ANCHOR: card_queries
def Card.isCreature (c : Card) : Bool :=
  match c.cardType with
  | .creature _ _ => true
  | _ => false

def Card.power (c : Card) : Option Nat :=
  match c.cardType with
  | .creature p _ => some p
  | _ => none

def Card.toughness (c : Card) : Option Nat :=
  match c.cardType with
  | .creature _ t => some t
  | _ => none
-- ANCHOR_END: card_queries

-- ANCHOR: combat
structure Creature where
  name : String
  power : Nat
  toughness : Nat
  damage : Nat := 0
  deriving Repr

def Creature.fromCard (c : Card) : Option Creature :=
  match c.cardType with
  | .creature p t => some { name := c.name, power := p, toughness := t }
  | _ => none

def Creature.isAlive (c : Creature) : Bool :=
  c.damage < c.toughness

def Creature.takeDamage (c : Creature) (dmg : Nat) : Creature :=
  { c with damage := c.damage + dmg }

def Creature.canBlock (blocker attacker : Creature) : Bool :=
  blocker.isAlive && attacker.isAlive

def combat (attacker blocker : Creature) : Creature × Creature :=
  let attackerAfter := attacker.takeDamage blocker.power
  let blockerAfter := blocker.takeDamage attacker.power
  (attackerAfter, blockerAfter)
-- ANCHOR_END: combat

-- ANCHOR: hand
abbrev Hand := List Card

def Hand.playable (hand : Hand) (pool : ManaPool) : List Card :=
  hand.filter (fun c => pool.canAfford c.cost)

def Hand.creatures (hand : Hand) : List Card :=
  hand.filter Card.isCreature

def Hand.totalCost (hand : Hand) : Nat :=
  hand.foldl (fun acc c => acc + c.cost.total) 0
-- ANCHOR_END: hand

-- Formatting helpers for output
def formatCost (c : ManaCost) : String :=
  let parts := #[
    if c.colorless > 0 then s!"{c.colorless}" else "",
    String.mk (List.replicate c.white 'W'),
    String.mk (List.replicate c.blue 'U'),
    String.mk (List.replicate c.black 'B'),
    String.mk (List.replicate c.red 'R'),
    String.mk (List.replicate c.green 'G')
  ]
  let result := String.join (parts.toList.filter (· ≠ ""))
  if result.isEmpty then "0" else result

def formatCard (c : Card) : String :=
  let typeStr := match c.cardType with
    | .creature p t => s!"Creature {p}/{t}"
    | .instant => "Instant"
    | .sorcery => "Sorcery"
    | .enchantment => "Enchantment"
    | .artifact => "Artifact"
  s!"{c.name} ({formatCost c.cost}) - {typeStr}"

def formatCreature (c : Creature) : String :=
  let status := if c.isAlive then "alive" else "dead"
  s!"{c.name} {c.power}/{c.toughness} ({c.damage} damage, {status})"

def main : IO Unit := do
  IO.println "=== Magic: The Gathering Card System ===\n"

  -- Mana pool
  let pool : ManaPool := { red := 2, black := 3, colorless := 1 }
  IO.println s!"Mana available: {pool.total} total"

  -- Hand of cards
  let hand : Hand := [goblinGuide, searingSpear, dayOfJudgment, graveTitan, swordOfFire]
  IO.println s!"\nHand ({hand.length} cards):"
  for card in hand do
    let castable := if pool.canAfford card.cost then "✓" else "✗"
    IO.println s!"  {castable} {formatCard card}"

  -- Playable cards
  let playable := hand.playable pool
  IO.println s!"\nPlayable cards: {playable.length}"

  -- Creatures in hand
  let creatures := hand.creatures
  IO.println s!"Creatures in hand: {creatures.length}"

  -- Combat example
  IO.println "\n=== Combat Example ==="
  let attacker : Creature := { name := "Goblin Guide", power := 2, toughness := 2 }
  let blocker : Creature := { name := "Grizzly Bears", power := 2, toughness := 2 }

  IO.println s!"Attacker: {formatCreature attacker}"
  IO.println s!"Blocker:  {formatCreature blocker}"

  let (attackerAfter, blockerAfter) := combat attacker blocker
  IO.println "\nAfter combat:"
  IO.println s!"Attacker: {formatCreature attackerAfter}"
  IO.println s!"Blocker:  {formatCreature blockerAfter}"
