/**
 * SIM-07: Stadtplaner*in in Erdbebenregion — Spielbare Erdbeben-Simulation
 *
 * Du übernimmst 1975 als Bürgermeister*in eine Kleinstadt in einer Erdbebenregion.
 * Über 50 Jahre (bis 2025) wachsen die Einwohnerzahlen — du musst Wohnraum bauen.
 *
 * Du hast die Wahl:
 * - Slum-Häuser (5 €): schnell und billig, aber bei Beben tödlich
 * - Standard-Häuser (15 €): solide gebaut, halten kleinere Beben aus
 * - Erdbebensichere Häuser (40 €): teuer, aber sicher
 *
 * Erdbeben kommen mehrmals während des Spiels — manchmal stark, manchmal schwach.
 * Du gewinnst, wenn 2025 alle Familien wohnen UND weniger als 200 Menschen
 * durch Erdbeben gestorben sind UND du nicht pleite bist.
 *
 * Fachlich korrekt:
 * - Magnitude-Verteilung folgt Gutenberg-Richter (häufig schwach, selten stark)
 * - Schäden hängen exponentiell von Magnitude UND Bauqualität ab
 * - Die Botschaft: "Naturgefahr ≠ Naturkatastrophe" (Vulnerabilität entscheidet)
 */

import { GameEngine, type GameMeta } from '@core/game-engine'

const META: GameMeta = {
  id: 'sim-07',
  title: 'Stadtplaner*in in Erdbebenregion',
  description: '50 Jahre lang baust du eine Stadt in einer Erdbebenregion auf. Wieviele Menschenleben kannst du retten?',
  msPerTick: 4000,
  tickUnit: 'Jahr',
  maxTicks: 50,
  tutorialSteps: 4,
}

const START_YEAR = 1975

export interface BuildingType {
  id: string
  name: string
  emoji: string
  description: string
  cost: number
  capacity: number      // Wieviele Menschen wohnen drin
  quality: number       // 0..1 (Bruchresistenz)
  upkeep: number
}

export const BUILDING_TYPES: BuildingType[] = [
  {
    id: 'slum',
    name: 'Slum-Häuser',
    emoji: '🏚️',
    description: 'Sehr billig. Bewohner haben keine Wahl. Stürzt bei Beben ab Magnitude 5 ein.',
    cost: 30,
    capacity: 200,
    quality: 0.05,
    upkeep: 1,
  },
  {
    id: 'simple',
    name: 'Einfache Häuser',
    emoji: '🏘️',
    description: 'Solide Bauweise. Übersteht schwache Beben.',
    cost: 80,
    capacity: 150,
    quality: 0.35,
    upkeep: 3,
  },
  {
    id: 'reinforced',
    name: 'Verstärkte Häuser',
    emoji: '🏠',
    description: 'Mit Stahl verstärkt. Übersteht mittlere Beben gut.',
    cost: 180,
    capacity: 120,
    quality: 0.65,
    upkeep: 6,
  },
  {
    id: 'quake-proof',
    name: 'Erdbebensichere Häuser',
    emoji: '🏛️',
    description: 'Modernster Standard. Übersteht selbst starke Beben fast unbeschadet.',
    cost: 400,
    capacity: 100,
    quality: 0.92,
    upkeep: 12,
  },
  {
    id: 'school',
    name: 'Schule (sicher)',
    emoji: '🏫',
    description: 'Erdbebensicher. Senkt Opferzahlen bei Beben durch Aufklärung & Übungen.',
    cost: 250,
    capacity: 0,
    quality: 0.95,
    upkeep: 8,
  },
]

interface OwnedBuilding {
  typeId: string
  count: number
  damaged: number  // wieviele beschädigt nach letztem Beben
}

interface PastQuake {
  year: number
  magnitude: number
  deaths: number
  homeless: number
}

export class ErdbebenGame extends GameEngine {
  private buildings: OwnedBuilding[] = []
  private pastQuakes: PastQuake[] = []

  // Nicht untergebrachte Menschen (Wartende auf Wohnraum)
  private waiting = 0
  private hasSchool = false
  private nextQuakeIn = 0  // Ticks bis zum nächsten Beben (zufällig 6-12)
  private firedEvents = new Set<string>()

  constructor() {
    super(META)
    this.setupResources()
    this.setupGoals()
    this.setupTutorial()
    this.setupVariables()

    // Erstes Beben kommt nach 8-14 Jahren
    this.nextQuakeIn = 8 + Math.floor(Math.random() * 6)
  }

  private setupResources(): void {
    this.addResource({
      id: 'budget',
      name: 'Budget',
      icon: '💰',
      initial: 250,
      unit: '€',
      format: (v) => `${Math.round(v)} €`,
    })
    this.addResource({
      id: 'population',
      name: 'Bevölkerung',
      icon: '👥',
      initial: 500,
      unit: '',
      format: (v) => `${Math.round(v).toLocaleString('de-AT')}`,
    })
    this.addResource({
      id: 'housed',
      name: 'Wohnraum',
      icon: '🏠',
      initial: 0,
      unit: 'Plätze',
      format: (v) => `${Math.round(v).toLocaleString('de-AT')}`,
    })
    this.addResource({
      id: 'waiting',
      name: 'Ohne Wohnung',
      icon: '⛺',
      initial: 0,
      unit: 'Menschen',
      format: (v) => `${Math.round(v).toLocaleString('de-AT')}`,
    })
    this.addResource({
      id: 'deaths',
      name: 'Opfer (gesamt)',
      icon: '🕯️',
      initial: 0,
      unit: '',
      format: (v) => `${Math.round(v).toLocaleString('de-AT')}`,
    })
    this.addResource({
      id: 'lastQuake',
      name: 'Letzte Magnitude',
      icon: '📊',
      initial: 0,
      unit: 'M',
      format: (v) => v > 0 ? `M ${v.toFixed(1)}` : '—',
    })
  }

  private setupGoals(): void {
    this.addGoal({
      id: 'survive',
      title: 'Bis 2025 regieren',
      description: '50 Jahre Stadtplanung — von 1975 bis 2025.',
      check: (g) => (g as ErdbebenGame).tick >= 50,
      progress: (g) => Math.min(100, ((g as ErdbebenGame).tick / 50) * 100),
      required: true,
    })
    this.addGoal({
      id: 'housing',
      title: 'Alle Bewohner unterbringen',
      description: 'Maximal 50 Menschen ohne Wohnung am Ende.',
      check: (g) => (g as ErdbebenGame).waiting <= 50,
      progress: (g) => {
        const w = (g as ErdbebenGame).waiting
        return Math.max(0, Math.min(100, 100 - w / 5))
      },
      required: true,
    })
    this.addGoal({
      id: 'safe',
      title: 'Weniger als 200 Tote',
      description: 'Halte die Opferzahl durch Erdbeben unter 200.',
      check: (g) => g.getResource('deaths') < 200,
      progress: (g) => Math.max(0, Math.min(100, 100 - g.getResource('deaths') / 2)),
      required: true,
    })
    this.addGoal({
      id: 'budget',
      title: 'Nicht pleite gehen',
      description: 'Halte ein positives Budget.',
      check: (g) => g.getResource('budget') > 0,
      required: true,
    })
  }

  private setupTutorial(): void {
    this.setTutorial([
      {
        triggerTick: 0,
        title: 'Willkommen, Bürgermeister*in!',
        text: 'Es ist 1975. Du übernimmst eine Kleinstadt mit 500 Einwohnern in einer Erdbebenregion.\n\nIn den nächsten 50 Jahren werden viele neue Familien zuziehen. Du musst entscheiden: Welche Häuser baust du?\n\nVorsicht: Erdbeben kommen unangekündigt. Manche schwach, manche stark.',
        unlocks: ['budget'],
      },
      {
        triggerTick: 0,
        title: 'Wachstum & Wohnraum',
        text: 'Jedes Jahr wächst die Bevölkerung um etwa 80 Personen. Du musst rechtzeitig Wohnraum schaffen.\n\nMenschen ohne Wohnung warten in Notunterkünften — und sie werden unzufrieden. Bei Beben sterben sie überproportional oft.\n\nBaue klug voraus, nicht erst wenn es zu spät ist.',
        unlocks: ['population'],
      },
      {
        triggerTick: 0,
        title: 'Bauqualität entscheidet',
        text: 'Die wichtigste Frage: Wie stabil baust du?\n\n🏚️ Slum-Häuser: 30 € — wirken verlockend billig, aber bei Beben sterben viele Menschen darin.\n🏘️ Einfach: 80 € — übersteht schwache Beben.\n🏠 Verstärkt: 180 € — gute Wahl für mittlere Beben.\n🏛️ Erdbebensicher: 400 € — sicher, aber teuer.\n\n🏫 Eine Schule senkt zusätzlich die Opferzahlen durch Aufklärung.',
        unlocks: ['shop'],
      },
      {
        triggerTick: 0,
        title: 'Die zentrale Erkenntnis',
        text: 'Naturgefahren werden zu Naturkatastrophen — durch unsere Entscheidungen.\n\nGleiche Magnitude, andere Bauqualität: 5 Tote oder 500.\n\nDu hast 250 € Startbudget. Pro Jahr bekommst du Steuern (~20 € pro 1000 Einwohner). Wartung deiner Gebäude bezahlt sich davon.\n\nDeine Aufgabe: alle bis 2025 sicher unterbringen und unter 200 Opfer bleiben.\n\nLos geht\'s! 🏗️',
        unlocks: ['controls'],
      },
    ])
  }

  private setupVariables(): void {
    this.setVariable('totalCapacity', 0)
    this.setVariable('avgQuality', 0)
    this.setVariable('upkeepTotal', 0)
  }

  private recalc(): void {
    let cap = 0
    let qSum = 0
    let qCount = 0
    let upkeep = 0
    for (const b of this.buildings) {
      const t = BUILDING_TYPES.find(x => x.id === b.typeId)
      if (!t) continue
      const aliveCount = b.count - b.damaged
      cap += t.capacity * aliveCount
      qSum += t.quality * aliveCount
      qCount += aliveCount
      upkeep += t.upkeep * aliveCount
    }
    this.setVariable('totalCapacity', cap)
    this.setVariable('avgQuality', qCount > 0 ? qSum / qCount : 0)
    this.setVariable('upkeepTotal', upkeep)
  }

  buyBuilding(typeId: string): boolean {
    const t = BUILDING_TYPES.find(x => x.id === typeId)
    if (!t) return false
    const budget = this.getResource('budget')
    if (budget < t.cost) {
      this.addEvent('error', `Nicht genug Budget für ${t.name}`, 'warning')
      return false
    }
    this.changeResource('budget', -t.cost)

    const existing = this.buildings.find(x => x.typeId === typeId)
    if (existing) {
      existing.count++
    } else {
      this.buildings.push({ typeId, count: 1, damaged: 0 })
    }

    if (typeId === 'school') this.hasSchool = true
    this.recalc()
    this.addEvent('build', `${t.emoji} ${t.name} gebaut (-${t.cost} €)`, 'success')
    this.notify()
    return true
  }

  getOwnedBuildings(): OwnedBuilding[] {
    return this.buildings
  }

  getBuildingCount(id: string): number {
    return this.buildings.find(b => b.typeId === id)?.count ?? 0
  }

  getStartYear(): number { return START_YEAR }

  protected simulateTick(): void {
    // 1. Bevölkerung wächst
    const growth = 80 + Math.floor(Math.random() * 30) - 15
    this.changeResource('population', growth)

    // 2. Wohnraum berechnen
    const totalPop = this.getResource('population')
    const totalCap = this.getVariable('totalCapacity')
    const housed = Math.min(totalPop, totalCap)
    this.waiting = Math.max(0, totalPop - totalCap)
    this.setResource('housed', housed)
    this.setResource('waiting', this.waiting)

    // 3. Steuern (proportional zur untergebrachten Bevölkerung)
    const income = Math.round((housed / 1000) * 25 + 5)
    this.changeResource('budget', income)

    // 4. Wartungskosten
    const upkeep = this.getVariable('upkeepTotal')
    this.changeResource('budget', -upkeep)

    // 5. Erdbeben?
    this.nextQuakeIn--
    if (this.nextQuakeIn <= 0) {
      this.triggerEarthquake()
      // Nächstes Beben in 5-12 Jahren
      this.nextQuakeIn = 5 + Math.floor(Math.random() * 8)
    }

    // 6. Schäden über die Zeit reparieren (langsam)
    for (const b of this.buildings) {
      if (b.damaged > 0 && Math.random() < 0.3) {
        b.damaged--
      }
    }
    this.recalc()

    // 7. Events
    if (this.tick === 5 && this.waiting > 100 && !this.firedEvent('housing-1')) {
      this.addEvent('housing-1', '⚠️ Über 100 Menschen leben in Notunterkünften!', 'warning')
    }
    if (this.tick === 20 && this.getResource('deaths') === 0 && !this.firedEvent('praise-1')) {
      this.addEvent('praise-1', '👏 20 Jahre ohne Opfer — die Bürger danken dir!', 'success')
    }
    if (this.hasSchool && !this.firedEvent('school-built')) {
      this.addEvent('school-built', '🏫 Die neue Schule informiert die Bürger über Erdbebenschutz.', 'success')
      this.firedEvents.add('school-built')
    }
  }

  private triggerEarthquake(): void {
    // Magnitude folgt grob Gutenberg-Richter — kleinere Beben häufiger
    // 60% schwach (4-5), 30% mittel (5-6.5), 10% stark (6.5-8)
    const r = Math.random()
    let magnitude: number
    if (r < 0.6) magnitude = 4 + Math.random()
    else if (r < 0.9) magnitude = 5 + Math.random() * 1.5
    else magnitude = 6.5 + Math.random() * 1.5

    this.setResource('lastQuake', magnitude)

    // Schäden berechnen
    let totalDeaths = 0
    let totalHomeless = 0
    let totalDamaged = 0

    for (const b of this.buildings) {
      const t = BUILDING_TYPES.find(x => x.id === b.typeId)
      if (!t || t.capacity === 0) continue

      // Wahrscheinlichkeit, dass ein Gebäude einstürzt:
      // f(magnitude, quality)
      // Bei Magnitude 4 + quality 0.05 → ~30% collapse
      // Bei Magnitude 7 + quality 0.05 → ~95% collapse
      // Bei Magnitude 7 + quality 0.92 → ~10% collapse
      const stress = Math.max(0, (magnitude - 3) / 5)  // 0..1
      const collapseProbability = Math.max(0, Math.min(0.95, stress - t.quality * 0.9))

      const aliveCount = b.count - b.damaged
      let collapsedThisQuake = 0
      for (let i = 0; i < aliveCount; i++) {
        if (Math.random() < collapseProbability) {
          collapsedThisQuake++
        }
      }
      b.damaged += collapsedThisQuake
      totalDamaged += collapsedThisQuake

      // Tote pro eingestürztem Gebäude
      // Schule senkt um 50%
      const schoolFactor = this.hasSchool ? 0.5 : 1
      const deathsPerCollapse = Math.round(t.capacity * 0.15 * schoolFactor * (1 - t.quality * 0.5))
      totalDeaths += collapsedThisQuake * deathsPerCollapse
      totalHomeless += collapsedThisQuake * t.capacity
    }

    // Nicht-untergebrachte Menschen sterben überproportional
    if (this.waiting > 0) {
      const stress = Math.max(0, (magnitude - 3) / 5)
      const waitingDeaths = Math.round(this.waiting * stress * 0.15)
      totalDeaths += waitingDeaths
    }

    if (totalDeaths > 0) {
      this.changeResource('population', -totalDeaths)
      this.changeResource('deaths', totalDeaths)
    }

    this.pastQuakes.push({
      year: this.tick,
      magnitude,
      deaths: totalDeaths,
      homeless: totalHomeless,
    })

    // Event-Meldung
    if (magnitude < 5) {
      this.addEvent('quake', `📊 Schwaches Beben (M ${magnitude.toFixed(1)}). ${totalDeaths > 0 ? `${totalDeaths} Opfer.` : 'Keine Opfer.'}`, totalDeaths > 0 ? 'warning' : 'info')
    } else if (magnitude < 6.5) {
      this.addEvent('quake', `⚠️ Mittleres Beben (M ${magnitude.toFixed(1)}). ${totalDeaths} Opfer, ${totalDamaged} Häuser beschädigt.`, 'warning')
    } else {
      this.addEvent('quake', `🆘 STARKES BEBEN (M ${magnitude.toFixed(1)})! ${totalDeaths} Opfer, ${totalDamaged} Häuser zerstört.`, 'danger')
    }

    this.notify()
  }

  private firedEvent(id: string): boolean {
    if (this.firedEvents.has(id)) return true
    this.firedEvents.add(id)
    return false
  }

  getPastQuakes(): PastQuake[] {
    return this.pastQuakes
  }

  getNextQuakeIn(): number {
    return this.nextQuakeIn
  }

  protected checkLossCondition(): boolean {
    if (this.getResource('budget') < -300) return true
    if (this.getResource('deaths') > 1000) return true
    return false
  }
}
