import Phaser from 'phaser';
import { EventBus } from '../../core/EventBus';
import { GameClock } from '../../core/GameClock';
import { SeededRNG } from '../../core/SeededRNG';
import { Meters, freshNightState } from '../../core/meters';
import { drunkStage } from '../../rules/drunk';
import { generatePatron, idAge, _resetPatronSerial } from '../../patrons/generator';
import { renderDoll } from '../../patrons/doll';
import { dollPlan } from '../../patrons/dollPlan';
import type { Patron } from '../../data/types';
import { HudStub } from './HudStub';

const W = 640;
const H = 360;

interface Walker {
  patron: Patron;
  root: Phaser.GameObjects.Container;
  doll: Phaser.GameObjects.Image;
  speed: number;
}

// Phase-0 proof scene: generator + doll renderer + RNG determinism + clock all
// visibly working. Patrons stream across a rainy street; their ID card renders
// from the same data record. SPACE reseeds, D toggles ID cards.
export class ParadeScene extends Phaser.Scene {
  private bus!: EventBus;
  private clock!: GameClock;
  private rng!: SeededRNG;
  private meters!: Meters;
  private hud!: HudStub;
  private walkers: Walker[] = [];
  private seed = 4207;
  private spawnAccMs = 0;
  private showIds = true;
  private seedText!: Phaser.GameObjects.Text;
  private clockText!: Phaser.GameObjects.Text;

  constructor() {
    super('Parade');
  }

  create(): void {
    this.buildWorld();
    this.resetRun(this.seed);

    this.input.keyboard?.on('keydown-SPACE', () => this.resetRun(this.seed + 1));
    this.input.keyboard?.on('keydown-F', () => this.scene.start('FloorDemo')); // LANE-FLOOR demo
    this.input.keyboard?.on('keydown-D', () => {
      this.showIds = !this.showIds;
      for (const w of this.walkers) {
        (w.root.getByName('card') as Phaser.GameObjects.Container | null)?.setVisible(this.showIds);
      }
    });
  }

  private buildWorld(): void {
    // street
    this.add.rectangle(W / 2, H - 40, W, 80, 0x1a1a24); // footpath
    this.add.rectangle(W / 2, H / 2 - 40, W, H - 160, 0x0d0d16); // wall of night
    // kebab shop glow, stage left — the moral centre of the game
    this.add.rectangle(70, 120, 120, 90, 0x2a1c08);
    this.add.rectangle(70, 96, 100, 18, 0xd8a020, 0.9);
    this.add.text(34, 90, 'KEBABS', { fontFamily: 'monospace', fontSize: '12px', color: '#3a2404' });
    this.add.rectangle(70, 150, 100, 40, 0xe8c060, 0.12);
    // venue door, stage right
    this.add.rectangle(W - 60, 130, 90, 110, 0x181828);
    this.add.rectangle(W - 60, 90, 70, 14, 0xd03470, 0.9);
    this.add.text(W - 88, 84, 'NOT TONIGHT', { fontFamily: 'monospace', fontSize: '9px', color: '#2a0818' });
    this.add.rectangle(W - 60, 150, 26, 54, 0x05050a);
    // neon reflections on the footpath
    this.add.rectangle(70, H - 60, 90, 6, 0xd8a020, 0.15);
    this.add.rectangle(W - 60, H - 60, 60, 6, 0xd03470, 0.15);

    // rain
    const rainG = this.add.graphics();
    rainG.fillStyle(0x8899bb, 1);
    rainG.fillRect(0, 0, 1, 4);
    rainG.generateTexture('rainDrop', 1, 4);
    rainG.destroy();
    this.add.particles(0, 0, 'rainDrop', {
      x: { min: 0, max: W },
      y: -6,
      lifespan: 900,
      speedY: { min: 220, max: 300 },
      speedX: { min: -30, max: -10 },
      quantity: 2,
      alpha: { start: 0.5, end: 0.15 },
    });

    this.seedText = this.add.text(4, H - 12, '', { fontFamily: 'monospace', fontSize: '8px', color: '#667' });
    this.clockText = this.add.text(W - 60, 4, '', { fontFamily: 'monospace', fontSize: '8px', color: '#9fe8a0' });
    this.add.text(4, 14, 'SPACE reseed · D toggle IDs · F floor demo', { fontFamily: 'monospace', fontSize: '8px', color: '#556' });
  }

  private resetRun(seed: number): void {
    this.seed = seed;
    for (const w of this.walkers) w.root.destroy();
    this.walkers = [];
    _resetPatronSerial();

    this.bus?.removeAll();
    this.bus = new EventBus();
    this.rng = new SeededRNG(seed);
    this.clock = new GameClock(this.bus);
    this.meters?.destroy();
    this.meters = new Meters(this.bus, freshNightState('theRoyal', 0, 80));
    this.hud?.destroy();
    this.hud = new HudStub(this, this.bus);
    this.clock.start();

    this.bus.on('clock:tick', () => {
      // idle proof that the meter pipeline works: hype breathes with the clock
      this.bus.emit('meters:delta', { vibe: 0 });
    });

    this.seedText.setText(`seed ${seed}`);
  }

  private spawnWalker(): void {
    const patron = generatePatron({ rng: this.rng, nightDate: this.clock.nightDate }, this.clock.clockMin);
    const plan = dollPlan(patron, 'queue');
    const key = renderDoll(this, patron, 'queue');
    const y = H - 78 + (this.walkers.length % 5) * 6;

    const root = this.add.container(-40, y);
    const doll = this.add.image(0, 0, key).setOrigin(0.5, 1);
    root.add(doll);

    const stage = drunkStage(patron.intoxication);
    const label = this.add
      .text(0, 4, `${patron.archetype} ${patron.age} ${stage !== 'sober' ? stage : ''}`.trim(), {
        fontFamily: 'monospace',
        fontSize: '7px',
        color: stage === 'maggot' || stage === 'messy' ? '#e06060' : '#556',
      })
      .setOrigin(0.5, 0);
    root.add(label);

    const card = this.add.container(0, -plan.height - 18);
    card.setName('card');
    const idKey = renderDoll(this, patron, 'idPhoto');
    card.add(this.add.rectangle(0, 0, 58, 30, 0xdad4c4).setStrokeStyle(1, 0x555555));
    card.add(this.add.image(-22, 0, idKey).setScale(1));
    const fakeMark = patron.idCard.fake ? ' ?' : '';
    card.add(
      this.add
        .text(-8, -11, `${patron.idCard.name}\nID ${idAge(patron, this.clock.nightDate)}${fakeMark}`, {
          fontFamily: 'monospace',
          fontSize: '7px',
          color: '#222',
        })
        .setOrigin(0, 0),
    );
    card.setVisible(this.showIds);
    root.add(card);

    root.setDepth(y);
    this.walkers.push({ patron, root, doll, speed: 26 + (patron.dollSeed % 20) - plan.swayPx * 5 });
  }

  override update(_time: number, deltaMs: number): void {
    this.clock.update(deltaMs);
    this.clockText.setText(this.clock.label);

    this.spawnAccMs += deltaMs;
    const spawnEvery = 700;
    while (this.spawnAccMs > spawnEvery && this.walkers.length < 24) {
      this.spawnAccMs -= spawnEvery;
      this.spawnWalker();
    }

    for (const w of [...this.walkers]) {
      w.root.x += (w.speed * deltaMs) / 1000;
      const sway = dollPlan(w.patron, 'queue').swayPx;
      if (sway > 0) w.doll.x = Math.sin(w.root.x / (14 - sway * 3)) * sway;
      if (w.root.x > W + 40) {
        w.root.destroy();
        this.walkers.splice(this.walkers.indexOf(w), 1);
      }
    }
  }
}
