/**
 * Energiemix-Spiel — Canvas Renderer
 *
 * Ansicht: Weite Landschaft mit Stadt am rechten Rand, dazwischen
 * verschiedene Kraftwerke in deterministischen Positionen. Im Hintergrund
 * Berge. Über der Landschaft zieht Wetter (Wolken, Sonne).
 *
 * Animationen:
 * - Windräder drehen sich (Geschwindigkeit abhängig von Wind-Faktor)
 * - Solar-Panels glitzern
 * - Rauch aus Kohle/Gas-Schornsteinen (pulsiert mit Auslastung)
 * - Kühltürme mit Dampf
 * - Batteriespeicher zeigen Pulsieren
 * - Bei Blackout: Stadt wird dunkel
 *
 * Zeitleiste am unteren Rand mit Jahren und Blackout-Markern.
 */

import { EnergiemixGame, PLANT_TYPES } from './game'

interface PlacedPlant {
  typeId: string
  x: number        // 0..1 in Welt
  y: number        // 0..1 vertikal
  scale: number
  ownerId: string
  builtTick: number
}

export class EnergiemixRenderer {
  private canvas: HTMLCanvasElement
  private ctx: CanvasRenderingContext2D
  private game: EnergiemixGame
  private W = 0
  private H = 0
  private t = 0
  private animId = 0
  private placed: PlacedPlant[] = []
  private knownIds = new Set<string>()
  private lastBlackouts = 0
  private blackoutFlash = 0

  constructor(container: HTMLElement, game: EnergiemixGame) {
    this.game = game
    this.canvas = document.createElement('canvas')
    this.canvas.style.cssText = 'width:100%;display:block;border-radius:12px;background:#dce6ea;'
    container.appendChild(this.canvas)
    const ctx = this.canvas.getContext('2d')
    if (!ctx) throw new Error('Canvas not supported')
    this.ctx = ctx
    this.resize()
    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, 440)
    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 seededRand(seed: number): number {
    const x = Math.sin(seed * 12.9898 + 78.233) * 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 owned = this.game.getOwnedPlants()
    for (const p of owned) {
      for (let i = 0; i < p.count; i++) {
        const id = `${p.typeId}-${i}`
        if (!this.knownIds.has(id)) {
          this.knownIds.add(id)
          this.placed.push(this.placePlant(p.typeId, i))
        }
      }
    }

    // Blackout-Flash
    const blackouts = this.game.getResource('blackouts')
    if (blackouts > this.lastBlackouts) {
      this.blackoutFlash = 1.0
      this.lastBlackouts = blackouts
    }
    this.blackoutFlash = Math.max(0, this.blackoutFlash - 0.012)
  }

  private placePlant(typeId: string, index: number): PlacedPlant {
    // Stable deterministic placement by type+index.
    // Different plant types get different "zones":
    const seed = typeId.charCodeAt(0) * 97 + typeId.charCodeAt(1) * 13 + index * 41
    let xZone: [number, number] = [0.08, 0.68]
    let yZone: [number, number] = [0.48, 0.62]

    switch (typeId) {
      case 'wind':
        xZone = [0.05, 0.58]
        yZone = [0.25, 0.45]
        break
      case 'solar':
        xZone = [0.12, 0.60]
        yZone = [0.55, 0.68]
        break
      case 'hydro':
        xZone = [0.02, 0.18]
        yZone = [0.50, 0.62]
        break
      case 'coal':
      case 'gas':
        xZone = [0.18, 0.52]
        yZone = [0.45, 0.58]
        break
      case 'biomass':
        xZone = [0.25, 0.58]
        yZone = [0.52, 0.62]
        break
      case 'nuclear':
        xZone = [0.32, 0.50]
        yZone = [0.44, 0.56]
        break
      case 'battery':
        xZone = [0.55, 0.72]
        yZone = [0.60, 0.70]
        break
    }

    const rx = this.seededRand(seed)
    const ry = this.seededRand(seed + 7)
    return {
      typeId,
      x: xZone[0] + rx * (xZone[1] - xZone[0]),
      y: yZone[0] + ry * (yZone[1] - yZone[0]),
      scale: 0.9 + this.seededRand(seed + 13) * 0.25,
      ownerId: `${typeId}-${index}`,
      builtTick: this.game.getSnapshot().tick,
    }
  }

  private draw(): void {
    const ctx = this.ctx
    const W = this.W
    const H = this.H
    const tick = this.game.getSnapshot().tick
    const year = this.game.getStartYear() + tick
    const weather = this.game.getWeatherFactors()

    // Fortschritt 0..1 über die Spielzeit
    const progress = Math.min(1, tick / 25)
    // Himmel wird mit zunehmender Erneuerbar-Quote klarer
    const renewable = this.game.getResource('renewable') / 100

    // === HIMMEL ===
    const sky = ctx.createLinearGradient(0, 0, 0, H * 0.7)
    const smog = 0.3 * (1 - renewable)
    sky.addColorStop(0, `rgb(${180 + smog * 20}, ${205 + smog * 10}, ${225 - smog * 20})`)
    sky.addColorStop(1, `rgb(${220 + smog * 10}, ${230}, ${225 - smog * 10})`)
    ctx.fillStyle = sky
    ctx.fillRect(0, 0, W, H * 0.72)

    // === SONNE ===
    const sunX = W * 0.82
    const sunY = H * 0.15
    const sunR = 22 * (0.8 + weather.solar * 0.3)
    const sunAlpha = Math.max(0.3, weather.solar)
    ctx.fillStyle = `rgba(250, 220, 140, ${sunAlpha})`
    ctx.beginPath()
    ctx.arc(sunX, sunY, sunR, 0, Math.PI * 2)
    ctx.fill()
    ctx.fillStyle = `rgba(250, 240, 200, ${sunAlpha * 0.3})`
    ctx.beginPath()
    ctx.arc(sunX, sunY, sunR * 1.6, 0, Math.PI * 2)
    ctx.fill()

    // === WOLKEN (verstärkt bei dunkler Solar-Faktor) ===
    const cloudCount = Math.round(3 + (1 - weather.solar) * 4)
    for (let i = 0; i < cloudCount; i++) {
      const cx = ((this.t * 6 + i * W / cloudCount) % (W + 80)) - 40
      const cy = H * 0.10 + i * 12
      this.drawCloud(cx, cy, 30 + i * 6, 0.75)
    }

    // === BERGE HINTEN ===
    ctx.fillStyle = '#8aa0a8'
    ctx.beginPath()
    ctx.moveTo(0, H * 0.52)
    for (let x = 0; x <= W; x += 40) {
      const s = Math.sin(x * 0.013 + 2) * 22 + Math.sin(x * 0.031) * 10
      ctx.lineTo(x, H * 0.52 + s)
    }
    ctx.lineTo(W, H * 0.72)
    ctx.lineTo(0, H * 0.72)
    ctx.closePath()
    ctx.fill()

    ctx.fillStyle = '#9fb2ba'
    ctx.beginPath()
    ctx.moveTo(0, H * 0.58)
    for (let x = 0; x <= W; x += 30) {
      const s = Math.sin(x * 0.019 + 4) * 18
      ctx.lineTo(x, H * 0.58 + s)
    }
    ctx.lineTo(W, H * 0.72)
    ctx.lineTo(0, H * 0.72)
    ctx.closePath()
    ctx.fill()

    // === BODEN ===
    const ground = ctx.createLinearGradient(0, H * 0.68, 0, H * 0.92)
    // Farbe wird mit Erneuerbar-Quote grüner
    const green = 140 + renewable * 30
    ground.addColorStop(0, `rgb(140, ${green}, 110)`)
    ground.addColorStop(1, `rgb(110, ${green - 20}, 90)`)
    ctx.fillStyle = ground
    ctx.fillRect(0, H * 0.68, W, H * 0.24)

    // === FLUSS am linken Rand (für Wasserkraft) ===
    ctx.fillStyle = `rgba(74, 124, 138, ${0.75 + weather.hydro * 0.2})`
    ctx.beginPath()
    ctx.moveTo(0, H * 0.70)
    ctx.quadraticCurveTo(W * 0.05, H * 0.80, W * 0.12, H * 0.85)
    ctx.lineTo(W * 0.14, H * 0.89)
    ctx.lineTo(0, H * 0.89)
    ctx.closePath()
    ctx.fill()

    // === STADT RECHTS ===
    this.drawCity(W * 0.75, H * 0.70, W * 0.22, H * 0.16, tick, this.blackoutFlash)

    // === KRAFTWERKE ===
    // Sortiere nach x für korrekte Tiefenordnung
    const sorted = [...this.placed].sort((a, b) => a.y - b.y)
    for (const p of sorted) {
      const px = p.x * W
      const py = p.y * H
      this.drawPlant(p, px, py, weather)
    }

    // === HUD ===
    this.drawHUD(year, tick)

    // === BLACKOUT-FLASH OVERLAY ===
    if (this.blackoutFlash > 0) {
      ctx.fillStyle = `rgba(40, 10, 10, ${this.blackoutFlash * 0.5})`
      ctx.fillRect(0, 0, W, H * 0.88)
    }

    // === ZEITLEISTE UNTEN ===
    this.drawTimeline()
  }

  private drawCloud(cx: number, cy: number, r: number, alpha: number): void {
    const ctx = this.ctx
    ctx.fillStyle = `rgba(255, 255, 255, ${alpha})`
    ctx.beginPath()
    ctx.arc(cx, cy, r * 0.55, 0, Math.PI * 2)
    ctx.arc(cx + r * 0.5, cy - 4, r * 0.45, 0, Math.PI * 2)
    ctx.arc(cx + r * 0.9, cy, r * 0.5, 0, Math.PI * 2)
    ctx.arc(cx + r * 0.4, cy + 5, r * 0.45, 0, Math.PI * 2)
    ctx.fill()
  }

  private drawCity(x: number, baseY: number, w: number, h: number, _tick: number, blackout: number): void {
    const ctx = this.ctx
    // Gebäude-Silhouetten (6 Türme)
    const towers = 6
    const litProbability = Math.max(0.1, 1 - blackout)
    for (let i = 0; i < towers; i++) {
      const seed = i * 11 + 3
      const r = this.seededRand(seed)
      const tw = (w / towers) * 0.8
      const th = h * (0.6 + r * 0.5)
      const tx = x + i * (w / towers)
      const ty = baseY - th
      ctx.fillStyle = '#4a4a55'
      ctx.fillRect(tx, ty, tw, th)
      // Fenster
      for (let wy = ty + 4; wy < baseY - 3; wy += 6) {
        for (let wx = tx + 2; wx < tx + tw - 2; wx += 5) {
          const on = this.seededRand(seed * 77 + wy * 5 + wx) < litProbability * 0.55
          ctx.fillStyle = on ? 'rgba(255, 220, 140, .9)' : 'rgba(80, 80, 95, .6)'
          ctx.fillRect(wx, wy, 2, 2)
        }
      }
    }
  }

  private drawPlant(p: PlacedPlant, x: number, y: number, weather: { wind: number; solar: number; hydro: number }): void {
    const ctx = this.ctx
    const s = p.scale

    switch (p.typeId) {
      case 'coal':
        this.drawCoalPlant(x, y, s)
        break
      case 'gas':
        this.drawGasPlant(x, y, s)
        break
      case 'hydro':
        this.drawHydroPlant(x, y, s)
        break
      case 'wind':
        this.drawWindTurbine(x, y, s, weather.wind)
        break
      case 'solar':
        this.drawSolarPanel(x, y, s)
        break
      case 'biomass':
        this.drawBiomassPlant(x, y, s)
        break
      case 'nuclear':
        this.drawNuclearPlant(x, y, s)
        break
      case 'battery':
        this.drawBattery(x, y, s)
        break
    }
    ctx.globalAlpha = 1
  }

  private drawCoalPlant(x: number, y: number, s: number): void {
    const ctx = this.ctx
    // Haupthalle
    ctx.fillStyle = '#6a6055'
    ctx.fillRect(x - 18 * s, y - 14 * s, 36 * s, 18 * s)
    ctx.fillStyle = '#4a4038'
    ctx.fillRect(x - 18 * s, y - 14 * s, 36 * s, 2 * s)
    // Schornsteine
    ctx.fillStyle = '#8a7868'
    ctx.fillRect(x - 12 * s, y - 30 * s, 5 * s, 18 * s)
    ctx.fillRect(x + 6 * s, y - 30 * s, 5 * s, 18 * s)
    // Rauch
    this.drawSmoke(x - 9 * s, y - 30 * s, 1.0, '#7a6a58')
    this.drawSmoke(x + 9 * s, y - 30 * s, 0.9, '#7a6a58')
  }

  private drawGasPlant(x: number, y: number, s: number): void {
    const ctx = this.ctx
    ctx.fillStyle = '#5a7a8a'
    ctx.fillRect(x - 14 * s, y - 10 * s, 28 * s, 14 * s)
    // Tank
    ctx.fillStyle = '#aabdc5'
    ctx.beginPath()
    ctx.arc(x - 8 * s, y - 2 * s, 6 * s, 0, Math.PI * 2)
    ctx.fill()
    // Schornstein
    ctx.fillStyle = '#7a8a95'
    ctx.fillRect(x + 6 * s, y - 22 * s, 3 * s, 14 * s)
    this.drawSmoke(x + 7 * s, y - 22 * s, 0.55, '#dddacc')
  }

  private drawHydroPlant(x: number, y: number, s: number): void {
    const ctx = this.ctx
    // Staumauer
    ctx.fillStyle = '#999a9c'
    ctx.fillRect(x - 12 * s, y - 18 * s, 24 * s, 22 * s)
    // Abflussöffnung
    ctx.fillStyle = '#3a5a6a'
    ctx.fillRect(x - 3 * s, y - 4 * s, 6 * s, 8 * s)
    // Wasserstrahl
    ctx.fillStyle = 'rgba(200, 230, 240, 0.7)'
    ctx.beginPath()
    ctx.moveTo(x - 3 * s, y + 4 * s)
    ctx.lineTo(x + 3 * s, y + 4 * s)
    ctx.lineTo(x + 8 * s, y + 12 * s)
    ctx.lineTo(x - 8 * s, y + 12 * s)
    ctx.closePath()
    ctx.fill()
  }

  private drawWindTurbine(x: number, y: number, s: number, windFactor: number): void {
    const ctx = this.ctx
    // Mast
    ctx.fillStyle = '#f0f0f0'
    ctx.fillRect(x - 1.2 * s, y - 30 * s, 2.4 * s, 44 * s)
    // Nabe
    ctx.fillStyle = '#e0e0e0'
    ctx.beginPath()
    ctx.arc(x, y - 30 * s, 2.5 * s, 0, Math.PI * 2)
    ctx.fill()
    // Rotor — dreht sich mit Windgeschwindigkeit
    const rot = this.t * windFactor * 1.8
    for (let i = 0; i < 3; i++) {
      const a = rot + (i * Math.PI * 2) / 3
      ctx.save()
      ctx.translate(x, y - 30 * s)
      ctx.rotate(a)
      ctx.fillStyle = '#fafafa'
      ctx.beginPath()
      ctx.moveTo(0, 0)
      ctx.lineTo(1.2 * s, -14 * s)
      ctx.lineTo(-1.2 * s, -14 * s)
      ctx.closePath()
      ctx.fill()
      ctx.restore()
    }
  }

  private drawSolarPanel(x: number, y: number, s: number): void {
    const ctx = this.ctx
    // 3 Panels in Reihe
    for (let i = 0; i < 3; i++) {
      const px = x + (i - 1) * 9 * s
      ctx.save()
      ctx.translate(px, y)
      // leichte Neigung
      ctx.transform(1, 0, -0.35, 0.82, 0, 0)
      ctx.fillStyle = '#1e3a5a'
      ctx.fillRect(-6 * s, -3 * s, 12 * s, 6 * s)
      // Gitter
      ctx.strokeStyle = '#3a5a7a'
      ctx.lineWidth = 0.5
      ctx.beginPath()
      for (let g = -5; g <= 5; g += 2) {
        ctx.moveTo(g * s, -3 * s)
        ctx.lineTo(g * s, 3 * s)
      }
      ctx.stroke()
      ctx.restore()
      // Ständer
      ctx.fillStyle = '#666'
      ctx.fillRect(px - 0.5, y + 2 * s, 1, 4 * s)
    }
  }

  private drawBiomassPlant(x: number, y: number, s: number): void {
    const ctx = this.ctx
    ctx.fillStyle = '#7a5a3a'
    ctx.fillRect(x - 13 * s, y - 10 * s, 26 * s, 14 * s)
    // Holzstapel
    ctx.fillStyle = '#8a6a4a'
    ctx.fillRect(x - 16 * s, y + 1 * s, 6 * s, 3 * s)
    ctx.fillRect(x - 16 * s, y - 2 * s, 6 * s, 3 * s)
    // Grüner Schornstein
    ctx.fillStyle = '#6a7a5a'
    ctx.fillRect(x + 5 * s, y - 22 * s, 3 * s, 14 * s)
    this.drawSmoke(x + 6.5 * s, y - 22 * s, 0.45, '#e0e0d0')
  }

  private drawNuclearPlant(x: number, y: number, s: number): void {
    const ctx = this.ctx
    // Reaktorkuppel
    ctx.fillStyle = '#c0c5c8'
    ctx.beginPath()
    ctx.arc(x - 10 * s, y - 4 * s, 8 * s, Math.PI, Math.PI * 2)
    ctx.fill()
    ctx.fillRect(x - 18 * s, y - 4 * s, 16 * s, 8 * s)
    // Kühlturm
    ctx.fillStyle = '#b0b5b8'
    ctx.beginPath()
    ctx.moveTo(x + 3 * s, y - 28 * s)
    ctx.lineTo(x + 14 * s, y - 28 * s)
    ctx.lineTo(x + 18 * s, y + 4 * s)
    ctx.lineTo(x - 1 * s, y + 4 * s)
    ctx.closePath()
    ctx.fill()
    // Dampf
    this.drawSmoke(x + 8.5 * s, y - 28 * s, 1.3, '#ffffff')
  }

  private drawBattery(x: number, y: number, s: number): void {
    const ctx = this.ctx
    // Container
    ctx.fillStyle = '#e8e8e8'
    ctx.fillRect(x - 12 * s, y - 8 * s, 24 * s, 14 * s)
    ctx.strokeStyle = '#888'
    ctx.lineWidth = 1
    ctx.strokeRect(x - 12 * s, y - 8 * s, 24 * s, 14 * s)
    // LEDs pulsieren
    const pulse = (Math.sin(this.t * 2) + 1) / 2
    ctx.fillStyle = `rgba(90, 200, 120, ${0.5 + pulse * 0.5})`
    for (let i = 0; i < 5; i++) {
      ctx.fillRect(x - 10 * s + i * 5 * s, y - 5 * s, 3 * s, 2 * s)
    }
    // Blitzsymbol
    ctx.fillStyle = '#d4a050'
    ctx.font = `bold ${7 * s}px sans-serif`
    ctx.textAlign = 'center'
    ctx.fillText('⚡', x, y + 4 * s)
  }

  private drawSmoke(x: number, y: number, intensity: number, color: string): void {
    const ctx = this.ctx
    for (let i = 0; i < 3; i++) {
      const off = (this.t * 8 + i * 6) % 18
      const alpha = Math.max(0, (1 - off / 18) * intensity * 0.7)
      ctx.fillStyle = color.startsWith('#') ? this.hexWithAlpha(color, alpha) : color
      ctx.globalAlpha = alpha
      ctx.beginPath()
      ctx.arc(x + Math.sin(off * 0.3) * 3, y - off, 3 + off * 0.25, 0, Math.PI * 2)
      ctx.fill()
    }
    ctx.globalAlpha = 1
  }

  private hexWithAlpha(hex: string, _a: number): string {
    return hex
  }

  private drawHUD(year: number, _tick: number): void {
    const ctx = this.ctx
    ctx.fillStyle = 'rgba(255,255,255,0.85)'
    ctx.fillRect(10, 10, 108, 36)
    ctx.strokeStyle = 'rgba(0,0,0,0.1)'
    ctx.lineWidth = 1
    ctx.strokeRect(10, 10, 108, 36)
    ctx.fillStyle = '#2a2a2a'
    ctx.font = 'bold 15px Inter, sans-serif'
    ctx.textAlign = 'left'
    ctx.fillText(`${year}`, 18, 28)
    ctx.fillStyle = '#6a6a6a'
    ctx.font = '9px Inter, sans-serif'
    const renewable = Math.round(this.game.getResource('renewable'))
    ctx.fillText(`🌱 ${renewable} % erneuerbar`, 18, 40)
  }

  private drawTimeline(): void {
    const ctx = this.ctx
    const W = this.W
    const H = this.H
    const tlY = H - 28
    const tlH = 22
    ctx.fillStyle = 'rgba(255,255,255,0.95)'
    ctx.fillRect(0, tlY, W, tlH)
    ctx.strokeStyle = 'rgba(0,0,0,0.06)'
    ctx.beginPath()
    ctx.moveTo(0, tlY + 0.5)
    ctx.lineTo(W, tlY + 0.5)
    ctx.stroke()

    const maxTicks = 25
    const tick = this.game.getSnapshot().tick
    const startYear = this.game.getStartYear()

    // Jahre-Marker alle 5 Jahre
    ctx.fillStyle = '#8a8a8a'
    ctx.font = '9px Inter, sans-serif'
    ctx.textAlign = 'center'
    for (let y = 0; y <= maxTicks; y += 5) {
      const x = (y / maxTicks) * W
      ctx.fillRect(x - 0.5, tlY + 2, 1, 5)
      ctx.fillText(`${startYear + y}`, x, tlY + 18)
    }

    // Aktueller Tick als Punkt
    const curX = (tick / maxTicks) * W
    ctx.fillStyle = '#4a7c8a'
    ctx.beginPath()
    ctx.arc(curX, tlY + 10, 4, 0, Math.PI * 2)
    ctx.fill()

    // Blackout-Marker
    const events = this.game.getSnapshot().events
    for (const e of events) {
      if (e.type === 'blackout' || e.type === 'peak-blackout') {
        const ex = (e.tick / maxTicks) * W
        ctx.fillStyle = '#b04a3a'
        ctx.beginPath()
        ctx.arc(ex, tlY + 10, 2.5, 0, Math.PI * 2)
        ctx.fill()
      }
    }
  }
}

// Re-export für Typ-Konsumierung durch UI
export type { PlantType } from './game'
