/**
 * SIM-07: Erdbeben-Simulator — LOGIK
 *
 * Modell:
 * - Zwei tektonische Platten bewegen sich gegeneinander
 * - Spannung baut sich auf (abhängig von Geschwindigkeit und Gesteinstyp)
 * - Bei Überschreitung der Bruchspannung → Erdbeben
 * - Magnitude abhängig von akkumulierter Spannung
 * - Auswirkungen auf zwei Städte (arm vs. reich) berechnet
 *
 * Didaktik:
 * - Fehlkonzepte: "Erdbeben sind zufällig", "Stärke = Schaden"
 * - Kernaussage: Gleiche Magnitude, unterschiedliche Auswirkungen
 */

import { Simulation, SimulationMeta } from '@core/simulation'

const META: SimulationMeta = {
  id: 'sim-07',
  name: 'Erdbeben-Simulator',
  educationLevels: [5, 6, 7, 8],
  primaryLevel: 5,
  kompetenzbereich: 'Leben und Wirtschaften unter Beachtung der natürlichen Prozesse',
  lernziele: [
    'Zusammenhang zwischen Plattenbewegung und Erdbeben verstehen',
    'Unterschied zwischen Magnitude und Schadensausmaß erkennen',
    'Ungleiche Betroffenheit durch Naturgefahren analysieren',
  ],
  basiskonzepte: ['Veränderung und Wandel', 'Gemeinsamkeiten und Unterschiede'],
  dpiMinuten: 25,
  typ: 'sachsimulation',
  tier: 1,
  requiresReading: true,
}

export interface QuakeEvent {
  time: number
  magnitude: number
  epicenterX: number
  depth: number
}

export interface CityImpact {
  name: string
  type: 'rich' | 'poor'
  distance: number
  damage: number          // 0-100%
  casualties: number      // estimated
  buildingCollapse: number // %
  recovery: string        // "Monate" | "Jahre" | "Jahrzehnte"
}

/**
 * Berechnet die Magnitude basierend auf akkumulierter Spannung
 * Vereinfachtes Gutenberg-Richter-artiges Modell
 */
export function computeMagnitude(stress: number, rockHardness: number): number {
  // log-Beziehung: mehr Spannung → exponentiell stärkeres Beben
  const base = Math.log10(Math.max(1, stress * rockHardness)) + 2
  return Math.min(9.5, Math.max(1, base))
}

/**
 * Berechnet die Auswirkungen auf eine Stadt
 */
export function computeCityImpact(
  magnitude: number,
  distance: number,
  buildingQuality: number  // 0-1 (0=schlecht, 1=erdbebensicher)
): CityImpact {
  // Intensität nimmt mit Entfernung ab (vereinfacht)
  const distanceFactor = Math.max(0.1, 1 - distance / 500)
  const intensity = magnitude * distanceFactor

  // Schaden abhängig von Bauqualität
  const rawDamage = Math.pow(intensity / 9, 2.5) * 100
  const damage = Math.min(100, rawDamage * (1 - buildingQuality * 0.8))

  // Opfer proportional zu Schaden und inverser Bauqualität
  const casualties = Math.round(damage * (1 - buildingQuality) * 5)

  // Gebäudekollaps
  const buildingCollapse = Math.min(100, rawDamage * (1 - buildingQuality * 0.9))

  // Erholungszeit
  let recovery = 'Wochen'
  if (damage > 70) recovery = 'Jahrzehnte'
  else if (damage > 40) recovery = 'Jahre'
  else if (damage > 15) recovery = 'Monate'

  return {
    name: '',
    type: buildingQuality > 0.6 ? 'rich' : 'poor',
    distance,
    damage: Math.round(damage),
    casualties,
    buildingCollapse: Math.round(buildingCollapse),
    recovery,
  }
}

export class ErdbebenSimulation extends Simulation {
  private stress = 0
  private quakeHistory: QuakeEvent[] = []
  private tickCount = 0

  constructor() {
    super(META)
    const ranges = this.getVariableRanges()
    for (const [key, range] of Object.entries(ranges)) {
      this.state.variables[key] = range.default
    }
  }

  getVariableRanges() {
    return {
      plateSpeed: {
        min: 1, max: 15, default: 5,
        unit: 'cm/Jahr', label: 'Plattengeschwindigkeit',
      },
      rockHardness: {
        min: 0.3, max: 1.5, default: 0.8,
        unit: '', label: 'Gesteinshärte',
      },
      buildingQualityA: {
        min: 0, max: 1, default: 0.8,
        unit: '', label: 'Bauqualität Stadt A (reich)',
      },
      buildingQualityB: {
        min: 0, max: 1, default: 0.2,
        unit: '', label: 'Bauqualität Stadt B (arm)',
      },
    }
  }

  /** Simuliert einen Tick (= 1 Jahr) */
  tick(): QuakeEvent | null {
    this.tickCount++
    const speed = this.getVariable('plateSpeed')
    const hardness = this.getVariable('rockHardness')

    // Spannung baut sich auf
    this.stress += speed * 0.1 * hardness

    // Bruchspannung (mit Zufallskomponente)
    const breakThreshold = 3 + Math.random() * 2

    if (this.stress >= breakThreshold) {
      const magnitude = computeMagnitude(this.stress, hardness)
      const quake: QuakeEvent = {
        time: this.tickCount,
        magnitude,
        epicenterX: 0.5 + (Math.random() - 0.5) * 0.2,
        depth: 5 + Math.random() * 50,
      }
      this.quakeHistory.push(quake)
      this.stress = this.stress * 0.1  // Spannungsabbau (nicht komplett)
      return quake
    }

    return null
  }

  getStress(): number { return this.stress; }
  getHistory(): QuakeEvent[] { return [...this.quakeHistory]; }

  /** Vergleicht Auswirkungen auf beide Städte */
  compareImpact(magnitude: number): { cityA: CityImpact; cityB: CityImpact } {
    const qualA = this.getVariable('buildingQualityA')
    const qualB = this.getVariable('buildingQualityB')

    const cityA = computeCityImpact(magnitude, 30, qualA)
    cityA.name = 'Stadt A (wohlhabend)'
    cityA.type = 'rich'

    const cityB = computeCityImpact(magnitude, 30, qualB)
    cityB.name = 'Stadt B (einkommensschwach)'
    cityB.type = 'poor'

    this.state.results = { cityA, cityB, magnitude }
    return { cityA, cityB }
  }

  compute() {
    return {
      stress: this.stress,
      quakeCount: this.quakeHistory.length,
      lastMagnitude: this.quakeHistory.length > 0
        ? this.quakeHistory[this.quakeHistory.length - 1].magnitude
        : 0,
    }
  }

  protected onVariableChange(): void {}
}
