/**
 * Klimawächter — Canvas Renderer (V3)
 *
 * Designprinzipien (nach User-Feedback):
 * - RUHE: Kein Tag-Nacht-Wechsel, immer Tagslicht
 * - DEZENT: Jahreszeiten als sehr leichte Farbverschiebung, keine Vollbild-Effekte
 * - KLIMASTRESS sichtbar: Mit steigender Temperatur wird Himmel gelblicher,
 *   Land trockener — das ist die einzige langfristige Farbveränderung
 * - DETERMINISTISCHE BAUTEN: Position fest beim Bauen
 * - ZEITLEISTE am unteren Rand: 2025 ━━●━━━ 2100
 * - LEBEN am Rand: Möwen, Hintergrundschiffe, springender Fisch
 *
 * Zeitraum: 2025–2100 (75 Jahre, 75 Ticks)
 */

import { KlimawaechterGame } from './game'

interface PlacedObject {
  type: 'tree' | 'solar' | 'wind' | 'green-roof' | 'dike' | 'sea-wall'
  x: number          // 0..1
  scale: number
  ownerId: string
  builtTick: number
}

interface Bird {
  x: number
  y: number
  vx: number
  wingPhase: number
  size: number
}

interface BgShip {
  x: number
  speed: number
  size: number
}

export class KlimawaechterRenderer {
  private canvas: HTMLCanvasElement
  private ctx: CanvasRenderingContext2D
  private game: KlimawaechterGame
  private W = 0
  private H = 0
  private t = 0
  private animId = 0
  private placed: PlacedObject[] = []
  private knownIds = new Set<string>()
  private lastTick = -1
  private tickStartT = 0

  private birds: Bird[] = []
  private bgShips: BgShip[] = []
  private fishTimer = 0
  private fishX = 0
  private fishPhase = -1

  private houseSeeds: number[] = []
  private landSurfaceFn: (x: number) => number = () => 0

  constructor(container: HTMLElement, game: KlimawaechterGame) {
    this.game = game
    this.canvas = document.createElement('canvas')
    this.canvas.style.cssText = 'width:100%;display:block;border-radius:12px;background:#dde3da;'
    container.appendChild(this.canvas)
    const ctx = this.canvas.getContext('2d')
    if (!ctx) throw new Error('Canvas not supported')
    this.ctx = ctx

    this.resize()
    this.initFauna()
    window.addEventListener('resize', () => this.resize())
  }

  private resize(): void {
    const rect = this.canvas.parentElement!.getBoundingClientRect()
    const dpr = window.devicePixelRatio || 1
    this.W = rect.width
    this.H = Math.min(rect.width * 0.55, 420)
    this.canvas.width = this.W * dpr
    this.canvas.height = this.H * dpr
    this.canvas.style.height = this.H + 'px'
    this.ctx.setTransform(dpr, 0, 0, dpr, 0, 0)
  }

  private initFauna(): void {
    if (this.houseSeeds.length === 0) {
      for (let i = 0; i < 12; i++) {
        this.houseSeeds.push(this.seededRand(i * 7919) * 0.04 - 0.02)
      }
    }
    for (let i = 0; i < 4; i++) {
      this.birds.push({
        x: Math.random() * this.W,
        y: this.H * (0.05 + Math.random() * 0.18),
        vx: 0.15 + Math.random() * 0.2,
        wingPhase: Math.random() * Math.PI * 2,
        size: 3 + Math.random() * 3,
      })
    }
    this.bgShips = [
      { x: this.W * 0.1, speed: 0.05, size: 0.7 },
      { x: this.W * 0.6, speed: 0.03, size: 0.5 },
    ]
  }

  private seededRand(seed: number): number {
    const x = Math.sin(seed * 12.9898) * 43758.5453
    return x - Math.floor(x)
  }

  start(): void {
    let lastFrame = performance.now()
    const loop = (now: number) => {
      const dt = (now - lastFrame) / 1000
      lastFrame = now
      this.t += dt
      this.updateScene()
      this.draw()
      this.animId = requestAnimationFrame(loop)
    }
    this.animId = requestAnimationFrame(loop)
  }

  stop(): void {
    cancelAnimationFrame(this.animId)
  }

  private updateScene(): void {
    const snap = this.game.getSnapshot()

    if (snap.tick !== this.lastTick) {
      this.lastTick = snap.tick
      this.tickStartT = this.t
    }

    const owned = this.game.getOwnedMeasures()
    for (const m of owned) {
      for (let i = 0; i < m.count; i++) {
        const id = `${m.measureId}-${i}`
        if (!this.knownIds.has(id)) {
          this.knownIds.add(id)
          this.placed.push(this.placeMeasure(m.measureId, i, snap.tick))
        }
      }
    }

    for (const b of this.birds) {
      b.x += b.vx
      b.wingPhase += 0.18
      b.y += Math.sin(this.t * 0.6 + b.wingPhase * 0.3) * 0.1
      if (b.x > this.W + 30) {
        b.x = -30
        b.y = this.H * (0.05 + Math.random() * 0.18)
      }
    }
    for (const s of this.bgShips) {
      s.x += s.speed
      if (s.x > this.W + 80) s.x = -80
    }
  }

  private placeMeasure(id: string, index: number, tick: number): PlacedObject {
    const baseScale = 0.85 + this.seededRand(index * 991 + 31) * 0.3
    const stableId = `${id}-${index}`

    if (id === 'forest') {
      const slot = index % 6
      const x = 0.04 + slot * 0.025 + this.seededRand(index * 13 + 7) * 0.015
      return { type: 'tree', x, scale: baseScale, ownerId: stableId, builtTick: tick }
    }
    if (id === 'solar') {
      const slot = index % 5
      const x = 0.78 - slot * 0.035 + this.seededRand(index * 17 + 3) * 0.01
      return { type: 'solar', x, scale: 0.95, ownerId: stableId, builtTick: tick }
    }
    if (id === 'wind') {
      const slot = index % 4
      const x = 0.02 + slot * 0.04 + this.seededRand(index * 23 + 11) * 0.01
      return { type: 'wind', x, scale: 1, ownerId: stableId, builtTick: tick }
    }
    if (id === 'green-roof') {
      return { type: 'green-roof', x: 0, scale: 1, ownerId: stableId, builtTick: tick }
    }
    if (id === 'dike') {
      const slot = index % 4
      const x = 0.83 + slot * 0.035
      return { type: 'dike', x, scale: 1, ownerId: stableId, builtTick: tick }
    }
    if (id === 'sea-wall') {
      const x = 0.95
      return { type: 'sea-wall', x, scale: 1 + index * 0.08, ownerId: stableId, builtTick: tick }
    }
    if (id === 'bikes') {
      return { type: 'bikes', x: 0.35 + index * 0.04, scale: 1, ownerId: stableId, builtTick: tick }
    }
    if (id === 'mangrove') {
      const x = 0.75 + index * 0.03
      return { type: 'mangrove', x, scale: baseScale, ownerId: stableId, builtTick: tick }
    }
    if (id === 'sand-fill') {
      const x = 0.82 + index * 0.025
      return { type: 'sand-fill', x, scale: 1, ownerId: stableId, builtTick: tick }
    }
    if (id === 'coal') {
      return { type: 'coal', x: 0.12, scale: 1 + index * 0.05, ownerId: stableId, builtTick: tick }
    }
    if (id === 'airport') {
      return { type: 'airport', x: 0.55, scale: 1, ownerId: stableId, builtTick: tick }
    }
    if (id === 'cloud-seed') {
      return { type: 'cloud-seed', x: 0.5, scale: 1, ownerId: stableId, builtTick: tick }
    }
    return { type: 'tree', x: 0.5, scale: 1, ownerId: stableId, builtTick: tick }
  }

  // ============================================================
  // RENDERING
  // ============================================================

  private draw(): void {
    const { ctx, W, H } = this
    ctx.clearRect(0, 0, W, H)

    const snap = this.game.getSnapshot()
    const co2 = snap.resources.co2 ?? 425
    const temp = snap.resources.temperature ?? 15
    const seaCm = snap.resources.sealevel ?? 0
    const flooded = snap.resources.flooded ?? 0
    const speed = snap.speed || 1

    // Klimastress: subtiler Farbwandel über die Zeit
    // Temperatur 15 → 19+ → Himmel wird gelblicher, Land trockener
    const tempStress = Math.max(0, Math.min(1, (temp - 15) / 4))
    const co2Stress = Math.max(0, Math.min(1, (co2 - 400) / 400))

    // Saison-Fortschritt innerhalb des aktuellen Jahres (für sehr dezente Akzente)
    const msPerTick = 4000 / Math.max(0.001, speed)
    const elapsedInTick = (this.t - this.tickStartT) * 1000
    const tickProgress = Math.min(1, elapsedInTick / msPerTick)
    const seasonF = tickProgress * 4
    const seasonIdx = Math.floor(seasonF) % 4
    const seasonBlend = seasonF - Math.floor(seasonF)

    // Reservierter Bereich für die Zeitleiste am unteren Rand
    const timelineH = 28
    const sceneH = H - timelineH
    const groundY = sceneH * 0.7
    const baseSeaY = sceneH * 0.78
    const seaY = baseSeaY - Math.min(baseSeaY * 0.2, seaCm * 0.4)

    // ===== HIMMEL — basiert auf Klimastress, NICHT auf Tageszeit =====
    const skyTopBase = [200, 215, 210]   // hell-bläulich
    const skyMidBase = [215, 225, 215]
    const skyBottomBase = [225, 230, 215]

    // Klimastress: Himmel wird gelb-bräunlicher
    const stressedSky = (base: number[]) => {
      const r = Math.round(base[0] + tempStress * 25 + co2Stress * 10)
      const g = Math.round(base[1] + tempStress * 5 - co2Stress * 5)
      const b = Math.round(base[2] - tempStress * 30 - co2Stress * 25)
      return `rgb(${r},${g},${b})`
    }

    const sky = ctx.createLinearGradient(0, 0, 0, groundY)
    sky.addColorStop(0, stressedSky(skyTopBase))
    sky.addColorStop(0.6, stressedSky(skyMidBase))
    sky.addColorStop(1, stressedSky(skyBottomBase))
    ctx.fillStyle = sky
    ctx.fillRect(0, 0, W, groundY)

    // ===== SONNE — fix oben rechts, dezent =====
    const sunX = W * 0.85
    const sunY = sceneH * 0.13
    const sunGlow = ctx.createRadialGradient(sunX, sunY, 0, sunX, sunY, 60)
    sunGlow.addColorStop(0, 'rgba(255,235,180,0.35)')
    sunGlow.addColorStop(1, 'rgba(255,235,180,0)')
    ctx.fillStyle = sunGlow
    ctx.fillRect(sunX - 60, sunY - 60, 120, 120)
    // Sonnen-Farbe wird leicht orange-rot bei Klimastress
    const sunR = 240 + tempStress * 15
    const sunG = 200 - tempStress * 30
    const sunB = 100 - tempStress * 30
    ctx.fillStyle = `rgb(${sunR},${sunG},${sunB})`
    ctx.beginPath()
    ctx.arc(sunX, sunY, 18, 0, Math.PI * 2)
    ctx.fill()

    // ===== WOLKEN — dezent driftend =====
    const cloudOffset = this.t * 4
    for (let i = 0; i < 4; i++) {
      const baseX = (i / 4) * W * 1.4 - W * 0.1
      const cx = ((baseX + cloudOffset * (1 + i * 0.1)) % (W + 100)) - 50
      const cy = sceneH * (0.08 + i * 0.04)
      const cloudOpacity = 0.7 - co2Stress * 0.2
      this.drawCloud(ctx, cx, cy, 0.7 + (i % 3) * 0.15, `rgba(255,255,255,${cloudOpacity})`)
    }

    // ===== KEIL-INSEL — schräg ansteigend von rechts (Meer) nach links (Vulkan) =====
    // landSurface(x) = y-Koordinate der Landoberfläche an horizontaler Position x
    // Hinten/links hoch, vorne/rechts niedrig (sinkt knapp unter baseSeaY)
    const landHighY = groundY - 40        // linke Seite (hinter Vulkan)
    const landLowY  = baseSeaY - 6        // rechte Seite — knapp über Wasser
    const landSurface = (x: number): number => {
      const t = x / W                      // 0 links → 1 rechts
      // Leicht quadratisch abfallend für natürlicheren Keil
      const ease = t * t * 0.4 + t * 0.6
      const base = landHighY * (1 - ease) + landLowY * ease
      // Kleine Welligkeit
      return base + Math.sin(x * 0.02) * 3 + Math.sin(x * 0.006 + 1.2) * 4
    }
    // Speicher als Render-State für Maßnahmen-Platzierung
    this.landSurfaceFn = landSurface

    // Hintergrund-Berge (weit links, entsprechen weiterem Hinterland)
    const mountainR = 150 + tempStress * 25
    const mountainG = 165 - tempStress * 30
    const mountainB = 150 - tempStress * 35
    ctx.fillStyle = `rgb(${mountainR},${mountainG},${mountainB})`
    ctx.beginPath()
    ctx.moveTo(0, landSurface(0) - 20)
    for (let x = 0; x <= W * 0.6; x += 25) {
      const my = landSurface(x) - 30 - Math.sin(x * 0.007 + 1) * 18 - Math.sin(x * 0.014 + 0.3) * 10
      ctx.lineTo(x, my)
    }
    ctx.lineTo(W * 0.6, landSurface(W * 0.6))
    ctx.lineTo(0, landSurface(0))
    ctx.closePath()
    ctx.fill()

    // === VULKAN mit Gletscher-Deckel (links, ragt aus der Landschaft) ===
    const volcanoBaseX = W * 0.16
    const volcanoBaseY = landSurface(volcanoBaseX) - 2
    const volcanoHeight = 95  // flacher
    const volcanoHalfBase = 65 // breiter
    const volcanoTopHalf = 16  // breitere Spitze
    // Fels
    ctx.fillStyle = `rgb(${106 + tempStress * 20},${90 + tempStress * 10},${74})`
    ctx.beginPath()
    ctx.moveTo(volcanoBaseX - volcanoHalfBase, volcanoBaseY)
    ctx.lineTo(volcanoBaseX - volcanoTopHalf, volcanoBaseY - volcanoHeight)
    ctx.lineTo(volcanoBaseX + volcanoTopHalf, volcanoBaseY - volcanoHeight)
    ctx.lineTo(volcanoBaseX + volcanoHalfBase, volcanoBaseY)
    ctx.closePath()
    ctx.fill()
    // Krater-Delle
    ctx.fillStyle = 'rgba(0,0,0,0.25)'
    ctx.beginPath()
    ctx.ellipse(volcanoBaseX, volcanoBaseY - volcanoHeight + 1, volcanoTopHalf - 2, 2, 0, 0, Math.PI * 2)
    ctx.fill()
    // Gletscher-Deckel (1/3 der Höhe, opak, schrumpft mit Temperatur)
    const glacierFraction = Math.max(0, Math.min(1, 1 - (temp - 15) / 3))
    if (glacierFraction > 0.02) {
      const glacierFullH = volcanoHeight / 3
      const glacierH = glacierFullH * glacierFraction
      const glacierBaseY = volcanoBaseY - (volcanoHeight - glacierFullH + glacierFullH - glacierH)
      const grime = (1 - glacierFraction) * 40
      // Die Deckel-Form ist ein Trapez, breiter als der Vulkan-Top
      // Breiter: Eis deckt die gesamte Spitze ab (keine braunen Raender)
      const capBottomHalf = (volcanoTopHalf + 12) * (0.6 + glacierFraction * 0.4)
      const capTopHalf = (volcanoTopHalf + 4) * (0.7 + glacierFraction * 0.3)
      ctx.fillStyle = `rgb(${240 - grime},${246 - grime},${250 - grime})`
      ctx.beginPath()
      ctx.moveTo(volcanoBaseX - capBottomHalf, glacierBaseY)
      ctx.lineTo(volcanoBaseX - capTopHalf, glacierBaseY - glacierH)
      ctx.lineTo(volcanoBaseX + capTopHalf, glacierBaseY - glacierH)
      ctx.lineTo(volcanoBaseX + capBottomHalf, glacierBaseY)
      ctx.closePath()
      ctx.fill()
      // Schatten-Linie unten am Deckel
      ctx.strokeStyle = `rgba(140,150,160,${0.3 * glacierFraction})`
      ctx.lineWidth = 1
      ctx.beginPath()
      ctx.moveTo(volcanoBaseX - capBottomHalf, glacierBaseY)
      ctx.lineTo(volcanoBaseX + capBottomHalf, glacierBaseY)
      ctx.stroke()
    }

    // ===== LAND (Keil) — Grasfarbe verändert sich mit Klimastress =====
    const grassR = 140 + tempStress * 30
    const grassG = 165 - tempStress * 35
    const grassB = 110 - tempStress * 25
    ctx.fillStyle = `rgb(${grassR},${grassG},${grassB})`
    ctx.beginPath()
    ctx.moveTo(0, landSurface(0))
    for (let x = 0; x <= W; x += 10) {
      ctx.lineTo(x, landSurface(x))
    }
    // Rechte untere Ecke: in den Boden / unter die Wasserlinie
    ctx.lineTo(W, sceneH)
    ctx.lineTo(0, sceneH)
    ctx.closePath()
    ctx.fill()

    // Dünner Bodenstreifen direkt unter dem Gras
    ctx.fillStyle = `rgb(${110 + tempStress * 20},${100 - tempStress * 15},${80 - tempStress * 20})`
    for (let x = 0; x <= W; x += 4) {
      ctx.fillRect(x, landSurface(x) + 4, 4, 6)
    }

    // ===== BÄUME =====
    for (const obj of this.placed.filter(p => p.type === 'tree')) {
      const px = obj.x * W
      this.drawTree(ctx, px, landSurface(px) - 1, obj.scale, tempStress)
    }

    // ===== WINDRÄDER (stehen auf dem Keil — weiter oben links ist windiger) =====
    for (const obj of this.placed.filter(p => p.type === 'wind')) {
      const px = obj.x * W
      this.drawWind(ctx, px, landSurface(px) - 5, this.t)
    }

    // ===== HÄUSER — bevorzugt auf der höheren (linken) Seite =====
    const greenRoofs = this.placed.filter(s => s.type === 'green-roof').length
    const totalHouses = 12
    const floodedCount = Math.round((flooded / 100) * totalHouses)
    for (let i = 0; i < totalHouses; i++) {
      // Häuser eher im Mittelteil/links (0.28..0.72) — Tiefland rechts bleibt leer
      const x = (0.28 + (i / totalHouses) * 0.44 + this.houseSeeds[i] * 0.8) * W
      const isFlooded = i >= (totalHouses - floodedCount)
      const hasGreenRoof = i < greenRoofs
      this.drawHouse(ctx, x, landSurface(x) - 1, 0.95 + this.houseSeeds[i] * 4, isFlooded, hasGreenRoof)
    }

    // ===== SOLARANLAGEN =====
    for (const obj of this.placed.filter(p => p.type === 'solar')) {
      const px = obj.x * W
      this.drawSolar(ctx, px, landSurface(px) - 4)
    }

    // ===== MEER =====
    const seaR = 145 - tempStress * 10
    const seaG = 175 - tempStress * 15
    const seaB = 175 - tempStress * 5
    const seaGrad = ctx.createLinearGradient(0, seaY, 0, sceneH)
    seaGrad.addColorStop(0, `rgb(${seaR},${seaG},${seaB})`)
    seaGrad.addColorStop(1, `rgb(${seaR - 25},${seaG - 25},${seaB - 15})`)
    ctx.fillStyle = seaGrad
    ctx.fillRect(0, seaY, W, sceneH - seaY)

    // Hintergrundschiffe
    for (const ship of this.bgShips) {
      this.drawBgShip(ctx, ship.x, seaY - 4, ship.size)
    }

    // Wellen
    for (let i = 0; i < 4; i++) {
      ctx.beginPath()
      ctx.moveTo(0, seaY)
      for (let x = 0; x <= W; x += 4) {
        ctx.lineTo(x, seaY + Math.sin(x * 0.02 + this.t * (1 + i * 0.5)) * (1.2 + i))
      }
      ctx.lineTo(W, sceneH); ctx.lineTo(0, sceneH); ctx.closePath()
      ctx.fillStyle = `rgba(255,255,255,${0.04 - i * 0.008})`
      ctx.fill()
    }

    // Sonnenreflexion auf dem Wasser (immer, da Sonne fix oben)
    ctx.globalAlpha = 0.25
    ctx.fillStyle = `rgb(${sunR},${sunG},${sunB})`
    for (let i = 0; i < 5; i++) {
      const ry = seaY + 4 + i * 4
      const rw = 24 - i * 3 + Math.sin(this.t * 2 + i) * 3
      ctx.fillRect(sunX - rw / 2, ry, rw, 1)
    }
    ctx.globalAlpha = 1

    // ===== KÜSTENBAUWERKE =====
    for (const obj of this.placed.filter(p => p.type === 'sand-fill')) {
      // Sand-Aufschüttung: kleine Hügel an der Wasserlinie
      const sx = obj.x * W, sy = seaY
      ctx.fillStyle = '#d4c090'
      ctx.beginPath()
      ctx.ellipse(sx, sy, 12, 5, 0, Math.PI, 0)
      ctx.fill()
      ctx.fillStyle = '#c8b480'
      ctx.beginPath()
      ctx.ellipse(sx + 8, sy, 8, 3, 0, Math.PI, 0)
      ctx.fill()
    }
    for (const obj of this.placed.filter(p => p.type === 'mangrove')) {
      // Mangroven: grüne Büsche an der Uferlinie
      const mx = obj.x * W, my = seaY - 4
      ctx.fillStyle = '#2a6a3a'
      ctx.beginPath(); ctx.arc(mx, my, 6 * obj.scale, 0, Math.PI * 2); ctx.fill()
      ctx.fillStyle = '#3a8a4a'
      ctx.beginPath(); ctx.arc(mx + 4, my - 2, 4 * obj.scale, 0, Math.PI * 2); ctx.fill()
      // Wurzeln im Wasser
      ctx.strokeStyle = '#3a5a2a'; ctx.lineWidth = 1
      ctx.beginPath(); ctx.moveTo(mx - 3, my + 3); ctx.lineTo(mx - 5, my + 10); ctx.stroke()
      ctx.beginPath(); ctx.moveTo(mx + 2, my + 3); ctx.lineTo(mx + 4, my + 8); ctx.stroke()
    }
    for (const obj of this.placed.filter(p => p.type === 'dike')) {
      this.drawDike(ctx, obj.x * W, groundY)
    }
    for (const obj of this.placed.filter(p => p.type === 'sea-wall')) {
      this.drawSeaWall(ctx, obj.x * W, groundY - 18, baseSeaY)
    }
    // Kohlekraftwerk: vor dem Vulkan
    for (const obj of this.placed.filter(p => p.type === 'coal')) {
      const cx = obj.x * W, cy = this.landSurfaceFn(obj.x * W) - 5
      ctx.fillStyle = '#5a5a5a'
      ctx.fillRect(cx - 10, cy - 12, 20, 12)
      // Schornstein
      ctx.fillStyle = '#4a4a4a'
      ctx.fillRect(cx + 4, cy - 22, 6, 12)
      // Rauch
      ctx.fillStyle = 'rgba(80,80,80,0.3)'
      ctx.beginPath(); ctx.arc(cx + 7, cy - 26 - Math.sin(this.t) * 3, 4, 0, Math.PI * 2); ctx.fill()
      ctx.beginPath(); ctx.arc(cx + 9, cy - 32 - Math.sin(this.t * 0.7) * 4, 3, 0, Math.PI * 2); ctx.fill()
    }
    // Radwege: Fahrräder auf der Strasse (vor den Häusern)
    for (const obj of this.placed.filter(p => p.type === 'bikes')) {
      const bx = obj.x * W, by = groundY - 2
      // Kleines Fahrrad-Symbol
      ctx.strokeStyle = '#4a8a4a'; ctx.lineWidth = 1.2
      ctx.beginPath(); ctx.arc(bx - 3, by, 2.5, 0, Math.PI * 2); ctx.stroke()
      ctx.beginPath(); ctx.arc(bx + 3, by, 2.5, 0, Math.PI * 2); ctx.stroke()
      ctx.beginPath(); ctx.moveTo(bx - 3, by); ctx.lineTo(bx, by - 3); ctx.lineTo(bx + 3, by); ctx.stroke()
    }
    // Flughafen
    for (const obj of this.placed.filter(p => p.type === 'airport')) {
      const ax = obj.x * W, ay = groundY - 8
      // Landebahn
      ctx.fillStyle = '#5a5a5a'; ctx.fillRect(ax - 18, ay, 36, 4)
      ctx.strokeStyle = '#fff'; ctx.lineWidth = 0.5; ctx.setLineDash([3, 2])
      ctx.beginPath(); ctx.moveTo(ax - 16, ay + 2); ctx.lineTo(ax + 16, ay + 2); ctx.stroke()
      ctx.setLineDash([])
      // Flugzeug
      const flyX = ax + Math.sin(this.t * 0.3) * 40
      const flyY = ay - 15 - Math.abs(Math.sin(this.t * 0.3)) * 20
      ctx.fillStyle = '#eee'; ctx.globalAlpha = 0.7
      ctx.beginPath(); ctx.ellipse(flyX, flyY, 6, 1.5, Math.sin(this.t * 0.3) * 0.3, 0, Math.PI * 2); ctx.fill()
      ctx.globalAlpha = 1
    }
    // Wolkenimpfung
    for (const obj of this.placed.filter(p => p.type === 'cloud-seed')) {
      // Spezialwolke mit Partikeln
      const cx = W * 0.5 + Math.sin(this.t * 0.2) * 30, cy = H * 0.12
      ctx.fillStyle = 'rgba(200,220,240,0.4)'
      ctx.beginPath(); ctx.ellipse(cx, cy, 20, 8, 0, 0, Math.PI * 2); ctx.fill()
      ctx.beginPath(); ctx.ellipse(cx - 10, cy + 2, 14, 6, 0, 0, Math.PI * 2); ctx.fill()
      // Partikel
      ctx.fillStyle = 'rgba(180,200,220,0.3)'
      for (let i = 0; i < 4; i++) {
        const px = cx - 8 + i * 5 + Math.sin(this.t + i) * 2
        ctx.beginPath(); ctx.arc(px, cy + 10 + Math.sin(this.t * 2 + i) * 3, 1.5, 0, Math.PI * 2); ctx.fill()
      }
    }

    // ===== BEWOHNER =====
    const popLossPct = Math.max(0, 10000 - snap.resources.population) / 10000
    const peopleCount = Math.round(8 * (1 - popLossPct))
    for (let i = 0; i < peopleCount; i++) {
      const px = W * (0.22 + (i / 8) * 0.58 + Math.sin(this.t * 0.5 + i) * 0.003)
      const py = groundY - 1
      ctx.fillStyle = '#3a3a3a'
      ctx.fillRect(px - 1, py - 5, 2, 5)
      ctx.beginPath()
      ctx.arc(px, py - 6, 1.4, 0, Math.PI * 2)
      ctx.fill()
    }

    // ===== VÖGEL =====
    for (const b of this.birds) {
      this.drawBird(ctx, b)
    }

    // ===== SPRINGENDER FISCH =====
    this.fishTimer -= 0.016
    if (this.fishTimer <= 0) {
      this.fishTimer = 8 + Math.random() * 12
      this.fishX = W * (0.55 + Math.random() * 0.35)
      this.fishPhase = 0
    }
    if (this.fishPhase >= 0 && this.fishPhase < 1) {
      this.fishPhase += 0.018
      const fy = seaY - Math.sin(this.fishPhase * Math.PI) * 18
      const rot = -Math.PI * 0.3 + this.fishPhase * Math.PI * 0.6
      ctx.save()
      ctx.translate(this.fishX, fy)
      ctx.rotate(rot)
      ctx.globalAlpha = 0.5
      ctx.fillStyle = '#5a7a7e'
      ctx.beginPath()
      ctx.ellipse(0, 0, 5, 2, 0, 0, Math.PI * 2)
      ctx.fill()
      ctx.beginPath()
      ctx.moveTo(-5, 0); ctx.lineTo(-8, -2); ctx.lineTo(-8, 2); ctx.closePath()
      ctx.fill()
      ctx.restore()
      ctx.globalAlpha = 1
    }

    // ===== DEZENTE SAISON-AKZENTE (sehr klein, nicht aufdringlich) =====
    if (seasonIdx === 2) this.drawLeaves(ctx, seasonBlend, sceneH)
    if (seasonIdx === 3) this.drawSnow(ctx, seasonBlend, sceneH)

    // ===== ZEITLEISTE am unteren Rand =====
    this.drawTimeline(ctx, timelineH, snap.tick, snap.events)
  }

  // ============================================================
  // ZEITLEISTE
  // ============================================================

  private drawTimeline(ctx: CanvasRenderingContext2D, h: number, currentTick: number, events: any[]): void {
    const { W, H } = this
    const y = H - h
    const marginX = 40

    // Hintergrund
    ctx.fillStyle = 'rgba(255,255,255,0.92)'
    ctx.fillRect(0, y, W, h)
    ctx.strokeStyle = 'rgba(0,0,0,0.06)'
    ctx.lineWidth = 1
    ctx.beginPath()
    ctx.moveTo(0, y); ctx.lineTo(W, y)
    ctx.stroke()

    // Zeitleiste
    const lineY = y + h / 2 + 2
    const lineX0 = marginX
    const lineX1 = W - marginX

    // Linie
    ctx.strokeStyle = '#c8c4b8'
    ctx.lineWidth = 2
    ctx.lineCap = 'round'
    ctx.beginPath()
    ctx.moveTo(lineX0, lineY); ctx.lineTo(lineX1, lineY)
    ctx.stroke()

    // Dezimal-Markierungen (alle 10 Jahre)
    const totalTicks = 75
    for (let i = 0; i <= 7; i++) {
      const decade = i * 10
      const x = lineX0 + (decade / totalTicks) * (lineX1 - lineX0)
      ctx.strokeStyle = '#a8a497'
      ctx.lineWidth = 1
      ctx.beginPath()
      ctx.moveTo(x, lineY - 3); ctx.lineTo(x, lineY + 3)
      ctx.stroke()
      // Jahreszahl
      if (i === 0 || i === 7 || i % 2 === 0) {
        ctx.fillStyle = '#7a7468'
        ctx.font = '9px Inter, system-ui, sans-serif'
        ctx.textAlign = 'center'
        ctx.fillText(`${2025 + decade}`, x, lineY + 14)
      }
    }

    // Aktueller Stand — runder Marker
    const progress = Math.min(1, currentTick / totalTicks)
    const markerX = lineX0 + progress * (lineX1 - lineX0)

    // Track bis hierher leicht hervorheben
    ctx.strokeStyle = '#4a7c8a'
    ctx.lineWidth = 2
    ctx.beginPath()
    ctx.moveTo(lineX0, lineY); ctx.lineTo(markerX, lineY)
    ctx.stroke()

    // Marker-Kreis
    ctx.fillStyle = '#4a7c8a'
    ctx.beginPath()
    ctx.arc(markerX, lineY, 5, 0, Math.PI * 2)
    ctx.fill()
    ctx.fillStyle = '#fff'
    ctx.beginPath()
    ctx.arc(markerX, lineY, 2, 0, Math.PI * 2)
    ctx.fill()

    // Aktuelles Jahr über dem Marker
    const currentYear = 2025 + currentTick
    ctx.fillStyle = '#4a7c8a'
    ctx.font = 'bold 10px Inter, system-ui, sans-serif'
    ctx.textAlign = 'center'
    ctx.fillText(`${currentYear}`, markerX, lineY - 8)

    // Event-Marker auf der Linie (kleine Punkte)
    for (const ev of events) {
      if (ev.tick > currentTick) continue
      const ex = lineX0 + (ev.tick / totalTicks) * (lineX1 - lineX0)
      ctx.fillStyle = ev.severity === 'danger' ? '#c0503c' : ev.severity === 'warning' ? '#c4a35a' : ev.severity === 'success' ? '#5a8a5e' : '#8a8a8a'
      ctx.beginPath()
      ctx.arc(ex, lineY - 8, 2, 0, Math.PI * 2)
      ctx.fill()
    }
  }

  // ============================================================
  // DRAW HELPERS
  // ============================================================

  private drawCloud(ctx: CanvasRenderingContext2D, x: number, y: number, s: number, color: string): void {
    ctx.fillStyle = color
    ctx.beginPath()
    ctx.ellipse(x, y, 24*s, 9*s, 0, 0, Math.PI*2); ctx.fill()
    ctx.beginPath()
    ctx.ellipse(x-13*s, y+2*s, 17*s, 7*s, 0, 0, Math.PI*2); ctx.fill()
    ctx.beginPath()
    ctx.ellipse(x+14*s, y+2*s, 18*s, 7*s, 0, 0, Math.PI*2); ctx.fill()
  }

  private drawTree(ctx: CanvasRenderingContext2D, x: number, y: number, s: number, stress: number): void {
    // Bei Klimastress: Bäume werden bräunlicher
    const leafG = 130 - stress * 40
    const leafR = 90 + stress * 60
    const leafB = 80 - stress * 30
    const shadeG = 100 - stress * 35
    const shadeR = 70 + stress * 55
    const shadeB = 60 - stress * 25

    ctx.fillStyle = '#5a4a3a'
    ctx.fillRect(x - 1.5*s, y - 9*s, 3*s, 9*s)
    ctx.fillStyle = `rgb(${shadeR},${shadeG},${shadeB})`
    ctx.beginPath()
    ctx.arc(x - 4*s, y - 10*s, 6*s, 0, Math.PI * 2)
    ctx.fill()
    ctx.beginPath()
    ctx.arc(x + 4*s, y - 10*s, 6*s, 0, Math.PI * 2)
    ctx.fill()
    ctx.fillStyle = `rgb(${leafR},${leafG},${leafB})`
    ctx.beginPath()
    ctx.arc(x, y - 14*s, 7*s, 0, Math.PI * 2)
    ctx.fill()
    ctx.beginPath()
    ctx.arc(x - 3*s, y - 11*s, 5*s, 0, Math.PI * 2)
    ctx.fill()
    ctx.beginPath()
    ctx.arc(x + 3*s, y - 11*s, 5*s, 0, Math.PI * 2)
    ctx.fill()
  }

  private drawHouse(ctx: CanvasRenderingContext2D, x: number, y: number, s: number, flooded: boolean, greenRoof: boolean): void {
    if (flooded) {
      ctx.globalAlpha = 0.6
      ctx.fillStyle = '#a08878'
      ctx.fillRect(x - 7*s, y - 8*s, 14*s, 8*s)
      ctx.fillStyle = '#5a4a3a'
      ctx.fillRect(x - 7*s, y - 4*s, 14*s, 4*s)
      ctx.globalAlpha = 1
      return
    }

    // Wand
    ctx.fillStyle = '#e8d8b8'
    ctx.fillRect(x - 8*s, y - 14*s, 16*s, 14*s)

    // Dach
    if (greenRoof) {
      ctx.fillStyle = '#6aa86e'
    } else {
      ctx.fillStyle = '#b06a5a'
    }
    ctx.beginPath()
    ctx.moveTo(x - 10*s, y - 14*s)
    ctx.lineTo(x, y - 22*s)
    ctx.lineTo(x + 10*s, y - 14*s)
    ctx.closePath()
    ctx.fill()

    // Fenster
    ctx.fillStyle = '#a8c8d0'
    ctx.fillRect(x - 3*s, y - 11*s, 6*s, 5*s)
    // Tür
    ctx.fillStyle = '#6a4a3a'
    ctx.fillRect(x - 2*s, y - 5*s, 4*s, 5*s)
  }

  private drawSolar(ctx: CanvasRenderingContext2D, x: number, y: number): void {
    const tilt = -0.3
    ctx.save()
    ctx.translate(x, y)
    ctx.rotate(tilt)
    ctx.fillStyle = 'rgba(255,220,150,0.3)'
    ctx.fillRect(-10, -12, 20, 12)
    ctx.fillStyle = '#3a4a6a'
    ctx.fillRect(-8, -10, 16, 8)
    ctx.strokeStyle = '#5a6a8a'
    ctx.lineWidth = 0.5
    for (let i = -6; i <= 6; i += 4) {
      ctx.beginPath()
      ctx.moveTo(i, -10); ctx.lineTo(i, -2)
      ctx.stroke()
    }
    ctx.beginPath()
    ctx.moveTo(-8, -6); ctx.lineTo(8, -6)
    ctx.stroke()
    ctx.restore()
    ctx.fillStyle = '#5a5a5a'
    ctx.fillRect(x - 1, y - 8, 2, 8)
  }

  private drawWind(ctx: CanvasRenderingContext2D, x: number, y: number, t: number): void {
    ctx.fillStyle = '#e0dcd0'
    ctx.fillRect(x - 1.5, y - 30, 3, 30)
    ctx.beginPath()
    ctx.arc(x, y - 30, 2.5, 0, Math.PI * 2)
    ctx.fill()
    const angle = t * 1.8
    for (let i = 0; i < 3; i++) {
      const a = angle + (i / 3) * Math.PI * 2
      ctx.save()
      ctx.translate(x, y - 30)
      ctx.rotate(a)
      ctx.fillStyle = '#f0ece0'
      ctx.beginPath()
      ctx.ellipse(0, -8, 1.2, 10, 0, 0, Math.PI * 2)
      ctx.fill()
      ctx.restore()
    }
  }

  private drawDike(ctx: CanvasRenderingContext2D, x: number, groundY: number): void {
    ctx.fillStyle = '#8a7a6a'
    ctx.beginPath()
    ctx.moveTo(x - 12, groundY)
    ctx.lineTo(x - 6, groundY - 14)
    ctx.lineTo(x + 6, groundY - 14)
    ctx.lineTo(x + 12, groundY)
    ctx.closePath()
    ctx.fill()
    ctx.fillStyle = '#6a5a4a'
    ctx.fillRect(x - 7, groundY - 16, 14, 2)
  }

  private drawSeaWall(ctx: CanvasRenderingContext2D, x: number, topY: number, baseY: number): void {
    ctx.fillStyle = '#a8a8a8'
    ctx.fillRect(x - 4, topY, 8, baseY - topY + 10)
    ctx.fillStyle = '#888'
    ctx.fillRect(x - 5, topY, 10, 3)
  }

  private drawBird(ctx: CanvasRenderingContext2D, b: Bird): void {
    const wing = Math.sin(b.wingPhase) * 0.5
    ctx.globalAlpha = 0.5
    ctx.strokeStyle = '#3a3a3a'
    ctx.lineWidth = 1.3
    ctx.lineCap = 'round'
    ctx.beginPath()
    ctx.moveTo(b.x - b.size, b.y - wing * b.size)
    ctx.quadraticCurveTo(b.x, b.y + 1.5, b.x + b.size, b.y - wing * b.size)
    ctx.stroke()
    ctx.globalAlpha = 1
  }

  private drawBgShip(ctx: CanvasRenderingContext2D, x: number, y: number, s: number): void {
    ctx.globalAlpha = 0.4
    ctx.fillStyle = '#6a5a5a'
    ctx.beginPath()
    ctx.moveTo(x - 14 * s, y)
    ctx.lineTo(x - 11 * s, y + 5 * s)
    ctx.lineTo(x + 11 * s, y + 5 * s)
    ctx.lineTo(x + 14 * s, y)
    ctx.closePath()
    ctx.fill()
    ctx.strokeStyle = '#4a4a4a'
    ctx.lineWidth = 0.8
    ctx.beginPath()
    ctx.moveTo(x, y); ctx.lineTo(x, y - 14 * s)
    ctx.stroke()
    ctx.fillStyle = '#e8e3d8'
    ctx.beginPath()
    ctx.moveTo(x + 1, y - 13 * s)
    ctx.lineTo(x + 9 * s, y - 2 * s)
    ctx.lineTo(x + 1, y - 1 * s)
    ctx.closePath()
    ctx.fill()
    ctx.globalAlpha = 1
  }

  private drawLeaves(ctx: CanvasRenderingContext2D, blend: number, sceneH: number): void {
    // Sehr dezent — nur 4 Blätter
    ctx.globalAlpha = blend * 0.3
    for (let i = 0; i < 4; i++) {
      const lx = (i * 173 + this.t * 6) % this.W
      const ly = ((this.t * 8 + i * 89) % (sceneH * 0.7))
      ctx.fillStyle = i % 2 ? '#c87a3a' : '#a85a2a'
      ctx.beginPath()
      ctx.ellipse(lx, ly, 1.5, 0.8, this.t + i, 0, Math.PI * 2)
      ctx.fill()
    }
    ctx.globalAlpha = 1
  }

  private drawSnow(ctx: CanvasRenderingContext2D, blend: number, sceneH: number): void {
    // Sehr dezent — nur 8 Flocken
    ctx.globalAlpha = Math.min(1, blend * 1.5) * 0.3
    ctx.fillStyle = '#fff'
    for (let i = 0; i < 8; i++) {
      const sx = (i * 119 + this.t * 4) % this.W
      const sy = ((this.t * 10 + i * 89) % (sceneH * 0.85))
      ctx.beginPath()
      ctx.arc(sx + Math.sin(this.t + i) * 3, sy, 1, 0, Math.PI * 2)
      ctx.fill()
    }
    ctx.globalAlpha = 1
  }
}
