const CanvasEngine = require('../lib/canvas');
const LogoFetcher = require('../lib/logos');
const BackgroundManager = require('../lib/backgrounds');
const TextureManager = require('../lib/textures');
const Randomizer = require('../lib/randomizer');
const brandConfig = require('../config/brand.json');

class ComparisonGenerator {
  constructor() {
    this.logoFetcher = new LogoFetcher();
    this.backgroundManager = new BackgroundManager();
    this.textureManager = new TextureManager();
    this.randomizer = new Randomizer();
  }

  async generate(productA, productB, styleOverrides = {}) {
    console.log(`\n🎨 Generating comparison: ${productA} vs ${productB}`);

    // Generate style
    const style = styleOverrides.style
      ? this.randomizer.generateStyleWithOverrides('comparison', styleOverrides)
      : this.randomizer.generateStyle('comparison');

    console.log(`Style selected: ${style.background.id} | ${style.colorScheme.name} | ${style.layout.name}`);

    // Create canvas
    const canvas = new CanvasEngine();

    // Layer 1: Background
    await this.renderBackground(canvas, style);

    // Layer 2: Lighting effects
    this.addLightingEffects(canvas, style);

    // Fetch logos
    console.log('Fetching logos...');
    const [logoA, logoB] = await Promise.all([
      this.logoFetcher.fetchLogo(productA),
      this.logoFetcher.fetchLogo(productB)
    ]);

    // Calculate positions
    const positions = this.calculatePositions(style.layout);

    // Layer 3: Glass panels behind logos
    this.drawGlassPanels(canvas, positions, style);

    // Layer 4: Logos
    await this.drawLogos(canvas, logoA, logoB, positions);

    // Layer 5: VS element
    this.drawVSElement(canvas, style);

    // Layer 6: Subtle vignette
    this.addVignette(canvas);

    // Layer 7: Texture overlay for realism
    this.textureManager.applyTextureOverlay(canvas.ctx, canvas.width, canvas.height, style.colorScheme);

    console.log('✓ Image generated successfully!\n');

    return canvas.toBuffer('image/png');
  }

  async renderBackground(canvas, style) {
    // Use layered background system for depth and professional look
    await this.backgroundManager.renderLayeredBackground(style.background, canvas, style.colorScheme);
  }

  addLightingEffects(canvas, style) {
    const { ctx, width, height } = canvas;

    // Randomize light direction
    const lightDirections = [
      { x: 0.2, y: 0.2, name: 'top-left' },
      { x: 0.8, y: 0.2, name: 'top-right' },
      { x: 0.5, y: 0.1, name: 'top' },
      { x: 0.8, y: 0.5, name: 'right' }
    ];
    const lightDir = lightDirections[Math.floor(Math.random() * lightDirections.length)];

    // Key light (main directional light)
    const keyLight = ctx.createRadialGradient(
      width * lightDir.x, height * lightDir.y, 0,
      width * lightDir.x, height * lightDir.y, width * 0.9
    );
    keyLight.addColorStop(0, canvas.hexToRgba(style.colorScheme.accent, 0.15));
    keyLight.addColorStop(0.5, canvas.hexToRgba(style.colorScheme.accent, 0.05));
    keyLight.addColorStop(1, 'rgba(0, 0, 0, 0)');
    ctx.fillStyle = keyLight;
    ctx.fillRect(0, 0, width, height);

    // Fill light (opposite direction, softer)
    const fillLight = ctx.createRadialGradient(
      width * (1 - lightDir.x), height * (1 - lightDir.y), 0,
      width * (1 - lightDir.x), height * (1 - lightDir.y), width * 0.7
    );
    fillLight.addColorStop(0, 'rgba(255, 255, 255, 0.08)');
    fillLight.addColorStop(1, 'rgba(255, 255, 255, 0)');
    ctx.fillStyle = fillLight;
    ctx.fillRect(0, 0, width, height);

    // Enhanced rim lighting with color
    const rimGradient = ctx.createRadialGradient(
      width / 2, height / 2, 0,
      width / 2, height / 2, width * 0.8
    );
    rimGradient.addColorStop(0, 'rgba(255, 255, 255, 0)');
    rimGradient.addColorStop(0.7, 'rgba(255, 255, 255, 0)');
    rimGradient.addColorStop(1, canvas.hexToRgba(style.colorScheme.accent, 0.25));
    ctx.fillStyle = rimGradient;
    ctx.fillRect(0, 0, width, height);

    // Bokeh effects (depth of field simulation)
    this.addBokehEffects(canvas, style);

    // Ambient occlusion (subtle darkening in corners)
    const aoGradient = ctx.createRadialGradient(
      width / 2, height / 2, 0,
      width / 2, height / 2, width * 0.6
    );
    aoGradient.addColorStop(0, 'rgba(0, 0, 0, 0)');
    aoGradient.addColorStop(1, 'rgba(0, 0, 0, 0.2)');
    ctx.fillStyle = aoGradient;
    ctx.fillRect(0, 0, width, height);
  }

  addBokehEffects(canvas, style) {
    const { ctx, width, height } = canvas;
    ctx.save();

    // Random bokeh count (50-200)
    const bokehCount = 50 + Math.floor(Math.random() * 150);
    const colors = [style.colorScheme.primary, style.colorScheme.secondary, style.colorScheme.accent];

    for (let i = 0; i < bokehCount; i++) {
      const x = Math.random() * width;
      const y = Math.random() * height;

      // Depth-based sizing (simulating depth of field)
      const depth = Math.random();
      const size = (10 + Math.random() * 40) * (0.3 + depth * 0.7);
      const alpha = (0.05 + depth * 0.15) * (Math.random() > 0.5 ? 1 : 0.5);

      const color = colors[Math.floor(Math.random() * colors.length)];
      const bokeh = ctx.createRadialGradient(x, y, 0, x, y, size);
      bokeh.addColorStop(0, canvas.hexToRgba(color, alpha));
      bokeh.addColorStop(0.7, canvas.hexToRgba(color, alpha * 0.3));
      bokeh.addColorStop(1, 'rgba(0, 0, 0, 0)');

      ctx.fillStyle = bokeh;
      ctx.beginPath();
      ctx.arc(x, y, size, 0, Math.PI * 2);
      ctx.fill();
    }

    ctx.restore();
  }

  calculatePositions(layout) {
    const { width, height } = brandConfig.dimensions;
    const logoSize = brandConfig.logoSize.comparison;

    const posA = {
      x: layout.logoAPosition.x * width,
      y: layout.logoAPosition.y * height,
      size: logoSize
    };

    const posB = {
      x: layout.logoBPosition.x * width,
      y: layout.logoBPosition.y * height,
      size: logoSize
    };

    const vsPos = {
      x: width / 2,
      y: height / 2
    };

    return { posA, posB, vsPos };
  }

  drawGlassPanels(canvas, positions, style) {
    const panelSize = brandConfig.logoSize.comparison + 40;
    const halfPanel = panelSize / 2;

    // Randomize glass intensity for variety
    const intensities = ['subtle', 'medium', 'high'];
    const randomIntensity = intensities[Math.floor(Math.random() * intensities.length)];

    // Enhanced depth shadows (drawn first, behind panels)
    canvas.drawShadow(
      positions.posA.x - halfPanel,
      positions.posA.y - halfPanel,
      panelSize,
      panelSize,
      50,
      'rgba(0, 0, 0, 0.35)'
    );

    canvas.drawShadow(
      positions.posB.x - halfPanel,
      positions.posB.y - halfPanel,
      panelSize,
      panelSize,
      50,
      'rgba(0, 0, 0, 0.35)'
    );

    // Enhanced glass panel behind logo A
    canvas.drawGlassPanel(
      positions.posA.x - halfPanel,
      positions.posA.y - halfPanel,
      panelSize,
      panelSize,
      10,
      style.colorScheme,
      randomIntensity
    );

    // Enhanced glass panel behind logo B
    canvas.drawGlassPanel(
      positions.posB.x - halfPanel,
      positions.posB.y - halfPanel,
      panelSize,
      panelSize,
      10,
      style.colorScheme,
      randomIntensity
    );
  }

  async drawLogos(canvas, logoA, logoB, positions) {
    const logoSize = brandConfig.logoSize.comparison;

    // Draw logo A
    await canvas.drawImageFromBuffer(
      logoA,
      positions.posA.x,
      positions.posA.y,
      logoSize,
      logoSize,
      true
    );

    // Draw logo B
    await canvas.drawImageFromBuffer(
      logoB,
      positions.posB.x,
      positions.posB.y,
      logoSize,
      logoSize,
      true
    );
  }

  drawVSElement(canvas, style) {
    const { width, height } = brandConfig.dimensions;
    const vsX = width / 2;
    const vsY = height / 2;

    // Randomize energy effect type
    const energyEffects = ['burst', 'lightning', 'particles', 'lines', 'chromatic', 'combo'];
    const selectedEffect = energyEffects[Math.floor(Math.random() * energyEffects.length)];

    // Randomize intensity
    const intensities = ['subtle', 'medium', 'high'];
    const intensity = intensities[Math.floor(Math.random() * intensities.length)];

    // Apply energy effect BEFORE drawing VS element (so it appears behind)
    const vsSize = style.vsElement.size || 100;
    const accentColor = style.colorScheme.accent;

    switch (selectedEffect) {
      case 'burst':
        canvas.drawEnergyBurst(vsX, vsY, vsSize, accentColor, intensity);
        break;

      case 'lightning':
        // Lightning bolts to logos
        const positions = this.calculatePositions(style.layout);
        canvas.drawLightningBolt(vsX, vsY, positions.posA.x, positions.posA.y, accentColor, 2);
        canvas.drawLightningBolt(vsX, vsY, positions.posB.x, positions.posB.y, accentColor, 2);
        break;

      case 'particles':
        const particleCount = intensity === 'high' ? 40 : intensity === 'medium' ? 25 : 15;
        const colors = [style.colorScheme.primary, style.colorScheme.secondary, accentColor];
        canvas.drawParticleBurst(vsX, vsY, particleCount, colors, vsSize * 1.5);
        break;

      case 'lines':
        // Energy lines to logos
        const pos = this.calculatePositions(style.layout);
        canvas.drawEnergyLines(vsX, vsY, [pos.posA, pos.posB], accentColor);
        break;

      case 'chromatic':
        canvas.drawChromaticAberration(vsX, vsY, vsSize * 1.3, style.colorScheme, 4);
        break;

      case 'combo':
        // Combine burst + particles for dramatic effect
        canvas.drawEnergyBurst(vsX, vsY, vsSize, accentColor, 'high');
        const comboColors = [style.colorScheme.primary, style.colorScheme.secondary, accentColor];
        canvas.drawParticleBurst(vsX, vsY, 30, comboColors, vsSize * 1.8);
        break;
    }

    // Draw the actual VS element on top of energy effects
    canvas.drawVSElement(style.vsElement, vsX, vsY, style.colorScheme);
  }

  addVignette(canvas) {
    const { ctx, width, height } = canvas;

    const vignette = ctx.createRadialGradient(
      width / 2, height / 2, 0,
      width / 2, height / 2, width * 0.7
    );

    vignette.addColorStop(0, 'rgba(0, 0, 0, 0)');
    vignette.addColorStop(0.5, 'rgba(0, 0, 0, 0)');
    vignette.addColorStop(1, 'rgba(0, 0, 0, 0.3)');

    ctx.fillStyle = vignette;
    ctx.fillRect(0, 0, width, height);
  }

  // Batch generation
  async generateBatch(comparisons) {
    const results = [];

    for (const [productA, productB] of comparisons) {
      const buffer = await this.generate(productA, productB);
      results.push({
        productA,
        productB,
        buffer
      });
    }

    return results;
  }
}

module.exports = ComparisonGenerator;
