/**
 * Erdbeben-Spiel — Canvas Renderer
 *
 * Ansicht: Stadt von der Seite, im Vordergrund Häuser verschiedener Bauart,
 * im Hintergrund Berge und ein Verwerfungs-Hinweis (rot pulsierende Linie zeigt Stress).
 *
 * Bei Beben: kurzer Shake, einstürzende Häuser werden zu Trümmern.
 * Zeitleiste am Rand mit Markierungen für vergangene Beben.
 */

import { ErdbebenGame, BUILDING_TYPES } from './game'

interface PlacedBuilding {
  typeId: string
  x: number      // 0..1
  scale: number
  ownerId: string
  intact: boolean
  builtTick: number
}

export class ErdbebenRenderer {
  private canvas: HTMLCanvasElement
  private ctx: CanvasRenderingContext2D
  private game: ErdbebenGame
  private W = 0
  private H = 0
  private t = 0
  private animId = 0
  private placed: PlacedBuilding[] = []
  private knownIds = new Set<string>()
  private shake = 0
  private shakeUntil = 0
  private lastDeaths = 0
  private lastQuakeShown = 0

  constructor(container: HTMLElement, game: ErdbebenGame) {
    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()
    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 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 {
    // Add new buildings to scene
    const owned = this.game.getOwnedBuildings()
    let counterByType: Record<string, number> = {}

    for (const b of owned) {
      counterByType[b.typeId] = 0
      for (let i = 0; i < b.count; i++) {
        const id = `${b.typeId}-${i}`
        const intact = i >= b.damaged
        if (!this.knownIds.has(id)) {
          this.knownIds.add(id)
          this.placed.push(this.placeBuilding(b.typeId, i, this.game.getSnapshot().tick))
        }
        // Update intact state
        const obj = this.placed.find(p => p.ownerId === id)
        if (obj) obj.intact = intact
      }
    }

    // Trigger shake on new earthquake
    const snap = this.game.getSnapshot()
    const lastMag = snap.resources.lastQuake
    const deaths = snap.resources.deaths

    if (deaths > this.lastDeaths) {
      this.shake = lastMag * 1.5
      this.shakeUntil = this.t + 1.2
      this.lastDeaths = deaths
    }

    if (this.t > this.shakeUntil) {
      this.shake *= 0.85
      if (this.shake < 0.05) this.shake = 0
    }
  }

  private placeBuilding(typeId: string, index: number, tick: number): PlacedBuilding {
    const id = `${typeId}-${index}`
    // Position depends on type (different "districts")
    let x = 0.1
    let scale = 1
    if (typeId === 'slum') {
      // Slums on the far edges
      const slot = index % 8
      x = 0.04 + slot * 0.025 + this.seededRand(index * 13 + 7) * 0.015
      scale = 0.7 + this.seededRand(index * 19) * 0.2
    } else if (typeId === 'simple') {
      // Simple houses in the middle-left area
      const slot = index % 8
      x = 0.25 + slot * 0.04 + this.seededRand(index * 17 + 3) * 0.02
      scale = 0.85 + this.seededRand(index * 23) * 0.2
    } else if (typeId === 'reinforced') {
      // Reinforced in middle-right
      const slot = index % 6
      x = 0.55 + slot * 0.05 + this.seededRand(index * 29 + 5) * 0.02
      scale = 0.95 + this.seededRand(index * 31) * 0.15
    } else if (typeId === 'quake-proof') {
      // Quake-proof on the right
      const slot = index % 5
      x = 0.83 + slot * 0.025 + this.seededRand(index * 37 + 11) * 0.01
      scale = 1.05
    } else if (typeId === 'school') {
      // School at the center, slightly bigger
      x = 0.48
      scale = 1.4
    }
    return { typeId, x, scale, ownerId: id, intact: true, builtTick: tick }
  }

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

  private draw(): void {
    const { ctx, W, H } = this
    const snap = this.game.getSnapshot()
    const tick = snap.tick

    ctx.save()
    if (this.shake > 0.01) {
      const sx = (Math.random() - 0.5) * this.shake
      const sy = (Math.random() - 0.5) * this.shake
      ctx.translate(sx, sy)
    }

    ctx.clearRect(-20, -20, W + 40, H + 40)

    const timelineH = 28
    const sceneH = H - timelineH
    const groundY = sceneH * 0.78

    // Sky
    const sky = ctx.createLinearGradient(0, 0, 0, groundY)
    sky.addColorStop(0, '#c8d4d8')
    sky.addColorStop(0.6, '#d8e0d8')
    sky.addColorStop(1, '#e0e4d8')
    ctx.fillStyle = sky
    ctx.fillRect(0, 0, W, groundY)

    // Sun
    ctx.fillStyle = '#e8c84a'
    ctx.beginPath()
    ctx.arc(W * 0.85, sceneH * 0.13, 16, 0, Math.PI * 2)
    ctx.fill()

    // Background mountains
    ctx.fillStyle = '#9aa494'
    ctx.beginPath()
    ctx.moveTo(0, groundY)
    for (let x = 0; x <= W; x += 30) {
      const my = groundY - 35 - Math.sin(x * 0.005 + 1) * 18 - Math.sin(x * 0.013 + 0.3) * 10
      ctx.lineTo(x, my)
    }
    ctx.lineTo(W, groundY)
    ctx.closePath()
    ctx.fill()

    // Closer mountain layer (visualizing the fault zone)
    ctx.fillStyle = '#7a8474'
    ctx.beginPath()
    ctx.moveTo(0, groundY)
    for (let x = 0; x <= W; x += 25) {
      const my = groundY - 18 - Math.sin(x * 0.008 + 0.5) * 10
      ctx.lineTo(x, my)
    }
    ctx.lineTo(W, groundY)
    ctx.closePath()
    ctx.fill()

    // === Fault zone visualization ===
    // A zigzag red-pulsing line in the mountain that shows tectonic stress
    const nextIn = this.game.getNextQuakeIn ? this.game.getNextQuakeIn() : 5
    const stressLevel = Math.max(0, Math.min(1, (12 - nextIn) / 12))
    const pulseAlpha = (Math.sin(this.t * 2) * 0.3 + 0.5) * stressLevel
    ctx.strokeStyle = `rgba(180,80,60,${pulseAlpha * 0.5})`
    ctx.lineWidth = 1.5 + stressLevel * 1.5
    ctx.setLineDash([3, 4])
    ctx.beginPath()
    let lx = 0
    let ly = groundY - 25
    ctx.moveTo(lx, ly)
    for (let i = 0; i < 20; i++) {
      lx += W / 20
      ly = groundY - 22 + (Math.sin(i * 1.7) * 5) + (Math.cos(i * 0.9) * 3)
      ctx.lineTo(lx, ly)
    }
    ctx.stroke()
    ctx.setLineDash([])

    // Ground
    ctx.fillStyle = '#9a9a82'
    ctx.fillRect(0, groundY, W, sceneH - groundY)
    ctx.fillStyle = '#7a7a62'
    ctx.fillRect(0, groundY + 3, W, 5)

    // ===== BUILDINGS =====
    // Sort by x for correct depth
    const sorted = [...this.placed].sort((a, b) => a.x - b.x)
    for (const obj of sorted) {
      const x = obj.x * W
      this.drawBuilding(ctx, x, groundY, obj)
    }

    // ===== PEOPLE WAITING (left edge, in front) =====
    const waiting = snap.resources.waiting || 0
    const waitingDots = Math.min(20, Math.floor(waiting / 30))
    if (waitingDots > 0) {
      // Draw a small "tent camp" with stick figures
      for (let i = 0; i < waitingDots; i++) {
        const px = 8 + (i % 4) * 7 + Math.floor(i / 4) * 0.5
        const py = groundY - 1
        // Tent
        if (i % 4 === 0) {
          ctx.fillStyle = '#c4a880'
          ctx.beginPath()
          ctx.moveTo(px - 5, py)
          ctx.lineTo(px, py - 7)
          ctx.lineTo(px + 5, py)
          ctx.closePath()
          ctx.fill()
        }
        // Person
        ctx.fillStyle = '#3a3a3a'
        ctx.fillRect(px - 0.5, py - 4, 1, 4)
        ctx.beginPath()
        ctx.arc(px, py - 5, 1, 0, Math.PI * 2)
        ctx.fill()
      }
      // Label
      ctx.fillStyle = 'rgba(180,100,80,0.9)'
      ctx.font = 'bold 9px Inter, sans-serif'
      ctx.textAlign = 'left'
      ctx.fillText(`${Math.round(waiting)} ohne Wohnung`, 8, groundY - 30)
    }

    // ===== HUD =====
    const year = 1975 + tick
    ctx.fillStyle = 'rgba(255,255,255,0.9)'
    ctx.beginPath()
    ctx.roundRect(12, 12, 230, 28, 8)
    ctx.fill()
    ctx.fillStyle = '#1a1a1a'
    ctx.font = 'bold 12px Inter, sans-serif'
    ctx.textAlign = 'left'
    ctx.fillText(`Jahr ${year}`, 22, 30)
    ctx.fillStyle = '#5a5a5a'
    ctx.font = '10px Inter, sans-serif'
    ctx.fillText(`Bevölkerung: ${Math.round(snap.resources.population)} · Tote: ${Math.round(snap.resources.deaths)}`, 75, 30)

    // Stress indicator
    if (stressLevel > 0.5) {
      ctx.fillStyle = `rgba(180,80,60,${pulseAlpha})`
      ctx.font = 'bold 10px Inter, sans-serif'
      ctx.textAlign = 'right'
      ctx.fillText('⚠ Tektonische Spannung baut sich auf', W - 14, 28)
    }

    ctx.restore()  // shake

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

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

    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()

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

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

    const totalTicks = 50
    for (let i = 0; i <= 5; 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()
      ctx.fillStyle = '#7a7468'
      ctx.font = '9px Inter, system-ui, sans-serif'
      ctx.textAlign = 'center'
      ctx.fillText(`${1975 + decade}`, x, lineY + 14)
    }

    const progress = Math.min(1, currentTick / totalTicks)
    const markerX = lineX0 + progress * (lineX1 - lineX0)

    ctx.strokeStyle = '#4a7c8a'
    ctx.lineWidth = 2
    ctx.beginPath()
    ctx.moveTo(lineX0, lineY); ctx.lineTo(markerX, lineY)
    ctx.stroke()

    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()

    ctx.fillStyle = '#4a7c8a'
    ctx.font = 'bold 10px Inter, system-ui, sans-serif'
    ctx.textAlign = 'center'
    ctx.fillText(`${1975 + currentTick}`, markerX, lineY - 8)

    // Event markers — focus on quakes
    for (const ev of events) {
      if (ev.tick > currentTick) continue
      const ex = lineX0 + (ev.tick / totalTicks) * (lineX1 - lineX0)
      let color = '#8a8a8a'
      if (ev.severity === 'danger') color = '#c0503c'
      else if (ev.severity === 'warning') color = '#c4a35a'
      else if (ev.severity === 'success') color = '#5a8a5e'
      ctx.fillStyle = color
      ctx.beginPath()
      ctx.arc(ex, lineY - 8, 2.5, 0, Math.PI * 2)
      ctx.fill()
    }
  }

  // ============================================================
  // BUILDING DRAWING
  // ============================================================

  private drawBuilding(ctx: CanvasRenderingContext2D, x: number, baseY: number, obj: PlacedBuilding): void {
    const t = BUILDING_TYPES.find(b => b.id === obj.typeId)
    if (!t) return

    if (!obj.intact) {
      // Rubble
      ctx.fillStyle = '#7a6a5a'
      ctx.fillRect(x - 8 * obj.scale, baseY - 4 * obj.scale, 16 * obj.scale, 4 * obj.scale)
      ctx.fillStyle = '#5a4a3a'
      ctx.fillRect(x - 6 * obj.scale, baseY - 6 * obj.scale, 4 * obj.scale, 2 * obj.scale)
      ctx.fillRect(x + 1 * obj.scale, baseY - 6 * obj.scale, 5 * obj.scale, 2 * obj.scale)
      return
    }

    const s = obj.scale

    if (obj.typeId === 'slum') {
      // Wonky shack
      ctx.fillStyle = '#a89878'
      ctx.fillRect(x - 6 * s, baseY - 8 * s, 12 * s, 8 * s)
      ctx.fillStyle = '#8a7858'
      ctx.beginPath()
      ctx.moveTo(x - 7 * s, baseY - 8 * s)
      ctx.lineTo(x - 1, baseY - 12 * s)
      ctx.lineTo(x + 7 * s, baseY - 7 * s)
      ctx.closePath()
      ctx.fill()
      ctx.fillStyle = '#5a4a3a'
      ctx.fillRect(x - 1 * s, baseY - 4 * s, 2 * s, 4 * s)
    } else if (obj.typeId === 'simple') {
      // Simple house
      ctx.fillStyle = '#e8d8b8'
      ctx.fillRect(x - 8 * s, baseY - 12 * s, 16 * s, 12 * s)
      ctx.fillStyle = '#b06a5a'
      ctx.beginPath()
      ctx.moveTo(x - 10 * s, baseY - 12 * s)
      ctx.lineTo(x, baseY - 19 * s)
      ctx.lineTo(x + 10 * s, baseY - 12 * s)
      ctx.closePath()
      ctx.fill()
      ctx.fillStyle = '#a8c8d0'
      ctx.fillRect(x - 3 * s, baseY - 9 * s, 6 * s, 4 * s)
      ctx.fillStyle = '#6a4a3a'
      ctx.fillRect(x - 1.5 * s, baseY - 4 * s, 3 * s, 4 * s)
    } else if (obj.typeId === 'reinforced') {
      // Reinforced — slightly larger, concrete look
      ctx.fillStyle = '#c8c4b4'
      ctx.fillRect(x - 9 * s, baseY - 16 * s, 18 * s, 16 * s)
      // Visible reinforcement bands
      ctx.fillStyle = '#8a8478'
      ctx.fillRect(x - 9 * s, baseY - 13 * s, 18 * s, 1)
      ctx.fillRect(x - 9 * s, baseY - 7 * s, 18 * s, 1)
      // Roof
      ctx.fillStyle = '#7a6a5a'
      ctx.fillRect(x - 10 * s, baseY - 17 * s, 20 * s, 2 * s)
      // Windows
      ctx.fillStyle = '#a8c8d0'
      ctx.fillRect(x - 6 * s, baseY - 11 * s, 4 * s, 3 * s)
      ctx.fillRect(x + 2 * s, baseY - 11 * s, 4 * s, 3 * s)
      ctx.fillStyle = '#6a4a3a'
      ctx.fillRect(x - 1.5 * s, baseY - 5 * s, 3 * s, 5 * s)
    } else if (obj.typeId === 'quake-proof') {
      // Modern building — taller, gray, with steel framework
      ctx.fillStyle = '#b8c0c4'
      ctx.fillRect(x - 9 * s, baseY - 22 * s, 18 * s, 22 * s)
      // Steel frame visible
      ctx.strokeStyle = '#5a6a74'
      ctx.lineWidth = 0.8
      ctx.beginPath()
      ctx.moveTo(x - 9 * s, baseY - 22 * s); ctx.lineTo(x - 9 * s, baseY)
      ctx.moveTo(x + 9 * s, baseY - 22 * s); ctx.lineTo(x + 9 * s, baseY)
      ctx.moveTo(x - 9 * s, baseY - 18 * s); ctx.lineTo(x + 9 * s, baseY - 18 * s)
      ctx.moveTo(x - 9 * s, baseY - 11 * s); ctx.lineTo(x + 9 * s, baseY - 11 * s)
      ctx.stroke()
      // Many windows
      ctx.fillStyle = '#a8c8d0'
      for (let row = 0; row < 4; row++) {
        for (let col = 0; col < 3; col++) {
          ctx.fillRect(x - 7 * s + col * 5 * s, baseY - 20 * s + row * 5 * s, 3 * s, 3 * s)
        }
      }
      // Flat roof
      ctx.fillStyle = '#6a747c'
      ctx.fillRect(x - 10 * s, baseY - 23 * s, 20 * s, 2 * s)
    } else if (obj.typeId === 'school') {
      // School — wider, low building, with flag
      ctx.fillStyle = '#e8e0c8'
      ctx.fillRect(x - 14 * s, baseY - 14 * s, 28 * s, 14 * s)
      // Roof
      ctx.fillStyle = '#5a8a5e'
      ctx.beginPath()
      ctx.moveTo(x - 16 * s, baseY - 14 * s)
      ctx.lineTo(x, baseY - 22 * s)
      ctx.lineTo(x + 16 * s, baseY - 14 * s)
      ctx.closePath()
      ctx.fill()
      // Door
      ctx.fillStyle = '#5a4a3a'
      ctx.fillRect(x - 2 * s, baseY - 7 * s, 4 * s, 7 * s)
      // Windows
      ctx.fillStyle = '#a8c8d0'
      ctx.fillRect(x - 11 * s, baseY - 11 * s, 5 * s, 4 * s)
      ctx.fillRect(x + 6 * s, baseY - 11 * s, 5 * s, 4 * s)
      // Flagpole
      ctx.strokeStyle = '#5a5a5a'
      ctx.lineWidth = 1
      ctx.beginPath()
      ctx.moveTo(x, baseY - 22 * s); ctx.lineTo(x, baseY - 30 * s)
      ctx.stroke()
      ctx.fillStyle = '#c0503c'
      ctx.beginPath()
      ctx.moveTo(x, baseY - 30 * s); ctx.lineTo(x + 6 * s, baseY - 28 * s); ctx.lineTo(x, baseY - 26 * s)
      ctx.closePath()
      ctx.fill()
    }
  }
}
