/**
 * Klimawächter — Mechanik-Trace
 *
 * Spielt das Klimawächter-Spiel rein rechnerisch über alle 75 Jahre für
 * verschiedene Strategien durch und gibt die Schlüssel-Variablen als
 * ASCII-Tabellen aus. Dient zur Analyse der Spielmechanik:
 * - Steigt CO₂ ohne Maßnahmen?
 * - Wie reagiert die Temperatur auf verschiedene Strategien?
 * - Wann wird die Stadt überflutet?
 * - Sind die Maßnahmen sinnvoll dimensioniert?
 *
 * Wird mit `npx vitest run sim-05-trace` aufgerufen.
 * Test schlägt nie fehl — er druckt nur.
 */

import { describe, it } from 'vitest'
import { KlimawaechterGame, MEASURES } from '../../src/sims/sim-05-treibhaus/game'

interface TraceRow {
  tick: number
  co2: number
  temp: number
  sea: number
  flooded: number
  budget: number
  pop: number
  measures: Record<string, number>
}

interface Strategy {
  name: string
  buy: (g: KlimawaechterGame, tick: number) => void
}

function runStrategy(strat: Strategy): TraceRow[] {
  const game = new KlimawaechterGame()
  // Tutorial überspringen, in 'playing' wechseln
  ;(game as any).state = 'playing'
  ;(game as any).tutorialStep = (game as any).tutorialSteps.length
  const rows: TraceRow[] = []

  // Startzustand auch erfassen
  const snapshot0 = (): TraceRow => ({
    tick: 0,
    co2: game.getResource('co2'),
    temp: game.getResource('temperature'),
    sea: game.getResource('sealevel'),
    flooded: game.getResource('flooded'),
    budget: game.getResource('budget'),
    pop: game.getResource('population'),
    measures: countMeasures(game),
  })
  rows.push(snapshot0())

  // 75 Ticks (= 75 Jahre)
  for (let i = 1; i <= 75; i++) {
    strat.buy(game, i)
    // simulateTick ist protected → cast
    ;(game as any).simulateTick()
    ;(game as any).tick = i
    rows.push({
      tick: i,
      co2: game.getResource('co2'),
      temp: game.getResource('temperature'),
      sea: game.getResource('sealevel'),
      flooded: game.getResource('flooded'),
      budget: game.getResource('budget'),
      pop: game.getResource('population'),
      measures: countMeasures(game),
    })
  }
  return rows
}

function countMeasures(game: KlimawaechterGame): Record<string, number> {
  const result: Record<string, number> = {}
  for (const m of MEASURES) {
    result[m.id] = game.getMeasureCount(m.id)
  }
  return result
}

function fmtRow(r: TraceRow): string {
  const m = Object.entries(r.measures).filter(([_, c]) => c > 0).map(([k, c]) => `${k}:${c}`).join(',') || '-'
  return [
    String(2025 + r.tick).padStart(4),
    r.co2.toFixed(0).padStart(5),
    r.temp.toFixed(2).padStart(6),
    r.sea.toFixed(1).padStart(6),
    r.flooded.toFixed(0).padStart(4),
    r.budget.toFixed(0).padStart(6),
    String(r.pop).padStart(6),
    m.padStart(20),
  ].join(' │ ')
}

function printTrace(name: string, rows: TraceRow[]) {
  console.log('\n═══════════════════════════════════════════════════════════════════════════════════')
  console.log(`STRATEGIE: ${name}`)
  console.log('═══════════════════════════════════════════════════════════════════════════════════')
  console.log(' Jahr │   CO₂ │   Temp │  Meer │ Flut │ Budget │  Bev   │              Maßnahmen')
  console.log('──────┼───────┼────────┼───────┼──────┼────────┼────────┼──────────────────────')
  // Alle 5 Jahre + erstes + letztes
  for (const r of rows) {
    if (r.tick === 0 || r.tick === 75 || r.tick % 5 === 0) {
      console.log(fmtRow(r))
    }
  }
  // Endbewertung
  const last = rows[rows.length - 1]
  const won =
    last.tick >= 75 &&
    last.temp < 17 &&
    last.budget > 0 &&
    last.flooded < 30
  console.log('──────┴───────┴────────┴───────┴──────┴────────┴────────┴──────────────────────')
  console.log(`  Status: ${won ? '✅ GEWONNEN' : '❌ VERLOREN'}`)
}

// === Strategien ===
const strategies: Strategy[] = [
  {
    name: 'Nichts tun (Baseline)',
    buy: () => {},
  },
  {
    name: 'Nur Wälder (alle 3 Jahre einer)',
    buy: (g, t) => { if (t % 3 === 0) g.buyMeasure('forest') },
  },
  {
    name: 'Nur Solar (sobald leistbar)',
    buy: (g) => {
      while (g.getResource('budget') >= 200) {
        if (!g.buyMeasure('solar')) break
      }
    },
  },
  {
    name: 'Nur Wind (sobald leistbar)',
    buy: (g) => {
      while (g.getResource('budget') >= 400) {
        if (!g.buyMeasure('wind')) break
      }
    },
  },
  {
    name: 'Nur Deiche (gegen Überflutung)',
    buy: (g) => {
      while (g.getResource('budget') >= 300) {
        if (!g.buyMeasure('dike')) break
      }
    },
  },
  {
    name: 'Wälder + Solar gemischt',
    buy: (g, t) => {
      if (t % 4 === 0 && g.getResource('budget') >= 200) g.buyMeasure('solar')
      else if (g.getResource('budget') >= 50) g.buyMeasure('forest')
    },
  },
  {
    name: 'Optimal: Solar + Wind + 1 Deich',
    buy: (g, t) => {
      if (t === 5 && g.getResource('budget') >= 300) g.buyMeasure('dike')
      if (g.getResource('budget') >= 400) g.buyMeasure('wind')
      else if (g.getResource('budget') >= 200) g.buyMeasure('solar')
    },
  },
]

describe('Klimawächter — Mechanik-Trace über 75 Jahre', () => {
  for (const strat of strategies) {
    it(`Trace: ${strat.name}`, () => {
      const rows = runStrategy(strat)
      printTrace(strat.name, rows)
    })
  }
})
