import { Application, Container, Graphics, Ticker } from 'pixi.js';

// Cinematic color palette
const COLORS = {
  wineRed: 0x2a0a0e,
  gold: 0xf0c239,
  goldDark: 0xd4a84b,
  goldLight: 0xffd700,
};

interface Particle {
  x: number;
  y: number;
  vx: number;
  vy: number;
  size: number;
  alpha: number;
  rotation: number;
  rotationSpeed: number;
  type: 'dust' | 'symbol' | 'streak';
  life: number;
  maxLife: number;
}

export class BackgroundEffect {
  private app: Application;
  private container: Container;
  private particles: Particle[] = [];
  private dustLayer: Graphics;
  private symbolLayer: Graphics;
  private streakLayer: Graphics;
  private time = 0;
  private windOffset = 0;
  private isDestroyed = false;

  // Configuration
  private readonly DUST_COUNT = 120;
  private readonly SYMBOL_COUNT = 25;
  private readonly STREAK_INTERVAL = 3000; // ms between streaks

  constructor() {
    this.app = new Application();
    this.container = new Container();
    this.dustLayer = new Graphics();
    this.symbolLayer = new Graphics();
    this.streakLayer = new Graphics();
  }

  async init(canvas: HTMLCanvasElement): Promise<void> {
    await this.app.init({
      canvas,
      width: window.innerWidth,
      height: window.innerHeight,
      backgroundColor: COLORS.wineRed,
      antialias: true,
      resolution: window.devicePixelRatio || 1,
      autoDensity: true,
    });

    // Setup layers (back to front)
    this.container.addChild(this.dustLayer);
    this.container.addChild(this.symbolLayer);
    this.container.addChild(this.streakLayer);
    this.app.stage.addChild(this.container);

    // Draw vignette overlay
    this.drawVignette();

    // Initialize particles
    this.initDustParticles();
    this.initSymbolParticles();

    // Start animation loop
    this.app.ticker.add(this.update.bind(this));

    // Spawn streaks periodically
    this.spawnStreakLoop();

    // Handle resize
    window.addEventListener('resize', this.handleResize.bind(this));
  }

  private drawVignette(): void {
    const vignette = new Graphics();
    const w = this.app.screen.width;
    const h = this.app.screen.height;
    const cx = w / 2;
    const cy = h / 2;
    const maxRadius = Math.sqrt(cx * cx + cy * cy);

    // Create radial gradient effect with multiple circles
    for (let i = 20; i >= 0; i--) {
      const ratio = i / 20;
      const radius = maxRadius * (0.3 + ratio * 0.7);
      const alpha = ratio * 0.8;

      vignette.circle(cx, cy, radius);
      vignette.fill({ color: 0x000000, alpha });
    }

    this.app.stage.addChildAt(vignette, 0);
  }

  private initDustParticles(): void {
    const w = this.app.screen.width;
    const h = this.app.screen.height;

    for (let i = 0; i < this.DUST_COUNT; i++) {
      this.particles.push({
        x: Math.random() * w,
        y: Math.random() * h,
        vx: (Math.random() - 0.5) * 0.3,
        vy: (Math.random() - 0.5) * 0.2,
        size: Math.random() * 2 + 1,
        alpha: Math.random() * 0.3 + 0.1,
        rotation: 0,
        rotationSpeed: 0,
        type: 'dust',
        life: 0,
        maxLife: Infinity,
      });
    }
  }

  private initSymbolParticles(): void {
    const w = this.app.screen.width;
    const h = this.app.screen.height;

    for (let i = 0; i < this.SYMBOL_COUNT; i++) {
      this.particles.push({
        x: Math.random() * w,
        y: h + Math.random() * 100,
        vx: (Math.random() - 0.5) * 0.5,
        vy: -Math.random() * 0.8 - 0.3,
        size: Math.random() * 8 + 4,
        alpha: Math.random() * 0.4 + 0.2,
        rotation: Math.random() * Math.PI * 2,
        rotationSpeed: (Math.random() - 0.5) * 0.02,
        type: 'symbol',
        life: 0,
        maxLife: Infinity,
      });
    }
  }

  private spawnStreak(): void {
    if (this.isDestroyed) return;

    const w = this.app.screen.width;
    const h = this.app.screen.height;
    const startX = Math.random() * w * 0.3;
    const startY = Math.random() * h * 0.3;

    this.particles.push({
      x: startX,
      y: startY,
      vx: Math.random() * 8 + 6,
      vy: Math.random() * 4 + 3,
      size: Math.random() * 3 + 2,
      alpha: 0.9,
      rotation: Math.atan2(4, 8),
      rotationSpeed: 0,
      type: 'streak',
      life: 0,
      maxLife: 60, // frames
    });
  }

  private spawnStreakLoop(): void {
    if (this.isDestroyed) return;

    this.spawnStreak();
    setTimeout(() => this.spawnStreakLoop(), this.STREAK_INTERVAL + Math.random() * 2000);
  }

  private update(ticker: Ticker): void {
    if (this.isDestroyed) return;

    this.time += ticker.deltaTime;
    this.windOffset = Math.sin(this.time * 0.01) * 0.5;

    // Clear graphics
    this.dustLayer.clear();
    this.symbolLayer.clear();
    this.streakLayer.clear();

    const w = this.app.screen.width;
    const h = this.app.screen.height;

    // Update and draw particles
    this.particles = this.particles.filter((p) => {
      // Update position with wind
      p.x += p.vx + this.windOffset * (p.type === 'dust' ? 0.3 : 0.1);
      p.y += p.vy;
      p.rotation += p.rotationSpeed;
      p.life++;

      // Check bounds and lifecycle
      if (p.type === 'streak') {
        if (p.life >= p.maxLife || p.x > w || p.y > h) {
          return false;
        }
        p.alpha = 0.9 * (1 - p.life / p.maxLife);
      } else if (p.type === 'symbol') {
        // Reset symbols that go off top
        if (p.y < -20) {
          p.y = h + 20;
          p.x = Math.random() * w;
        }
      } else {
        // Wrap dust particles
        if (p.x < 0) p.x = w;
        if (p.x > w) p.x = 0;
        if (p.y < 0) p.y = h;
        if (p.y > h) p.y = 0;
      }

      // Draw particle
      this.drawParticle(p);
      return true;
    });
  }

  private drawParticle(p: Particle): void {
    const layer = p.type === 'dust'
      ? this.dustLayer
      : p.type === 'symbol'
        ? this.symbolLayer
        : this.streakLayer;

    if (p.type === 'dust') {
      // Simple gold circle
      layer.circle(p.x, p.y, p.size);
      layer.fill({ color: COLORS.gold, alpha: p.alpha });
    } else if (p.type === 'symbol') {
      // Fortune symbols (circles and squares)
      layer.setTransform(p.x, p.y, 1, 1, p.rotation);

      if (Math.random() > 0.5) {
        // Circle
        layer.circle(0, 0, p.size);
      } else {
        // Square/diamond
        layer.rect(-p.size / 2, -p.size / 2, p.size, p.size);
      }
      layer.fill({ color: COLORS.goldDark, alpha: p.alpha });
      layer.setTransform(0, 0, 1, 1, 0);
    } else if (p.type === 'streak') {
      // Gold streak with trail
      const trailLength = 80;
      const dx = Math.cos(p.rotation);
      const dy = Math.sin(p.rotation);

      // Draw gradient trail
      for (let i = 0; i < 10; i++) {
        const ratio = i / 10;
        const tx = p.x - dx * trailLength * ratio;
        const ty = p.y - dy * trailLength * ratio;
        const ta = p.alpha * (1 - ratio) * 0.5;
        const ts = p.size * (1 - ratio * 0.5);

        layer.circle(tx, ty, ts);
        layer.fill({ color: COLORS.goldLight, alpha: ta });
      }

      // Draw head
      layer.circle(p.x, p.y, p.size);
      layer.fill({ color: COLORS.goldLight, alpha: p.alpha });
    }
  }

  private handleResize(): void {
    if (this.isDestroyed) return;

    this.app.renderer.resize(window.innerWidth, window.innerHeight);
  }

  destroy(): void {
    this.isDestroyed = true;
    window.removeEventListener('resize', this.handleResize.bind(this));
    this.app.destroy(true, { children: true });
  }
}
