const fetch = require('node-fetch');
const fs = require('fs').promises;
const path = require('path');
const CanvasEngine = require('./canvas');

class BackgroundManager {
  constructor() {
    this.backgroundsDir = path.join(__dirname, '../../public/assets/backgrounds');
    this.cacheDir = path.join(__dirname, '../../cache/backgrounds');
    this.ensureDirectories();
  }

  async ensureDirectories() {
    try {
      await fs.mkdir(this.backgroundsDir, { recursive: true });
      await fs.mkdir(this.cacheDir, { recursive: true });
    } catch (error) {
      console.error('Error creating directories:', error);
    }
  }

  // Fetch from Unsplash
  async fetchFromUnsplash(query, orientation = 'landscape') {
    try {
      const apiKey = process.env.UNSPLASH_ACCESS_KEY;
      if (!apiKey) {
        console.log('Unsplash API key not configured, using fallback');
        return null;
      }

      const url = `https://api.unsplash.com/photos/random?query=${query}&orientation=${orientation}&w=1200&h=675`;
      const response = await fetch(url, {
        headers: {
          'Authorization': `Client-ID ${apiKey}`
        },
        timeout: 5000
      });

      if (response.ok) {
        const data = await response.json();
        const imageUrl = data.urls.regular;

        // Download the image
        const imageResponse = await fetch(imageUrl, { timeout: 10000 });
        if (imageResponse.ok) {
          return await imageResponse.buffer();
        }
      }

      return null;
    } catch (error) {
      console.log('Unsplash fetch failed:', error.message);
      return null;
    }
  }

  // Render multi-layered background with depth
  async renderLayeredBackground(backgroundConfig, canvas, colorScheme) {
    const { type } = backgroundConfig;

    // Determine number of layers (random 3-5)
    const layerCount = 3 + Math.floor(Math.random() * 3);

    // Layer 1: Base background (existing logic)
    await this.renderBackground(backgroundConfig, canvas);

    // Layer 2: Depth gradient (atmospheric perspective)
    this.renderDepthLayer(canvas, colorScheme);

    // Layer 3: Mesh overlay (if not already a mesh)
    if (type !== 'pattern' && Math.random() > 0.3) {
      this.renderMeshOverlay(canvas, colorScheme);
    }

    // Layer 4: Light rays (randomized)
    if (Math.random() > 0.5) {
      this.renderLightRays(canvas, colorScheme);
    }

    // Layer 5: Particle layer with depth (only sometimes)
    if (layerCount >= 4 && Math.random() > 0.4) {
      this.renderFloatingParticles(canvas, colorScheme);
    }
  }

  // Render background based on style config
  async renderBackground(backgroundConfig, canvas) {
    const { type, id } = backgroundConfig;

    if (type === 'photo') {
      await this.renderPhotoBackground(backgroundConfig, canvas);
    } else if (type === 'gradient') {
      this.renderGradientBackground(backgroundConfig, canvas);
    } else if (type === 'pattern') {
      this.renderPatternBackground(backgroundConfig, canvas);
    } else if (type === 'particles') {
      this.renderParticlesBackground(backgroundConfig, canvas);
    } else if (type === 'wave') {
      this.renderWaveBackground(backgroundConfig, canvas);
    }
  }

  // Render photo background
  async renderPhotoBackground(config, canvas) {
    const { id, blur, overlay, brightness } = config;

    // Try to load local photo first
    const localPhotoPath = path.join(this.backgroundsDir, `${id}.jpg`);

    try {
      await fs.access(localPhotoPath);

      // Load and draw the photo
      const imgBuffer = await fs.readFile(localPhotoPath);
      const { loadImage } = require('canvas');
      const img = await loadImage(imgBuffer);

      // Draw image to fill canvas
      canvas.ctx.drawImage(img, 0, 0, canvas.width, canvas.height);

      // Apply blur if specified
      if (blur) {
        canvas.applyBlur(blur);
      }

      // Apply overlay
      if (overlay) {
        canvas.drawOverlay(overlay);
      }

      canvas.resetFilter();

    } catch (error) {
      console.log(`Local photo not found: ${id}, generating gradient fallback`);
      // Fallback to gradient
      this.renderGradientFallback(canvas);
    }
  }

  // Render gradient background
  renderGradientBackground(config, canvas) {
    const { colors, style } = config;

    if (style === 'mesh') {
      canvas.drawMeshGradient(colors);
    } else {
      const angle = Math.random() * 360;
      canvas.drawGradient(colors, angle);
    }
  }

  // Render pattern background
  renderPatternBackground(config, canvas) {
    const { shape, colors } = config;

    // Draw base gradient first
    canvas.drawGradient(colors, 45);

    // Add pattern overlay
    if (shape === 'hexagon' || shape === 'grid') {
      canvas.drawGeometricPattern(shape, colors, 50, 0.15);
    }
  }

  // Render particles background
  renderParticlesBackground(config, canvas) {
    const { colors } = config;

    // Draw base gradient
    canvas.drawGradient(colors, 135);

    // Add particles
    canvas.drawParticles(colors, 150);
  }

  // Render wave background
  renderWaveBackground(config, canvas) {
    const { colors } = config;

    // Draw solid base
    canvas.drawSolidBackground(colors[0]);

    // Draw waves
    canvas.drawWavePattern(colors, 80, 0.01);
  }

  // Gradient fallback when photo not available
  renderGradientFallback(canvas) {
    const fallbackColors = ['#667eea', '#764ba2'];
    canvas.drawGradient(fallbackColors, 45);
    canvas.drawOverlay(0.3);
  }

  // Create sample backgrounds
  async createSampleBackgrounds() {
    console.log('Creating sample backgrounds...');

    const sampleConfigs = [
      {
        id: 'modern-office-blur',
        type: 'gradient',
        colors: ['#1e3a8a', '#3b82f6', '#60a5fa'],
        style: 'mesh'
      },
      {
        id: 'coworking-space',
        type: 'gradient',
        colors: ['#7c3aed', '#a78bfa', '#c4b5fd'],
        style: 'mesh'
      },
      {
        id: 'conference-room',
        type: 'gradient',
        colors: ['#0f172a', '#1e293b', '#334155'],
        style: 'linear'
      },
      {
        id: 'home-office-setup',
        type: 'gradient',
        colors: ['#f59e0b', '#fbbf24', '#fcd34d'],
        style: 'mesh'
      },
      {
        id: 'tech-startup-vibe',
        type: 'gradient',
        colors: ['#ec4899', '#f472b6', '#fbcfe8'],
        style: 'mesh'
      }
    ];

    for (const config of sampleConfigs) {
      const canvas = new CanvasEngine();

      if (config.type === 'gradient') {
        if (config.style === 'mesh') {
          canvas.drawMeshGradient(config.colors);
        } else {
          canvas.drawGradient(config.colors, 45);
        }
      }

      canvas.drawOverlay(0.4);

      const outputPath = path.join(this.backgroundsDir, `${config.id}.jpg`);
      const buffer = canvas.toBuffer('image/jpeg');
      await fs.writeFile(outputPath, buffer);
      console.log(`✓ Created: ${config.id}.jpg`);
    }

    console.log('Sample backgrounds created!');
  }

  // Download backgrounds from Unsplash
  async downloadUnsplashBackgrounds() {
    const queries = [
      'modern office workspace',
      'coworking space',
      'conference room tech',
      'home office setup',
      'startup office'
    ];

    const ids = [
      'modern-office-blur',
      'coworking-space',
      'conference-room',
      'home-office-setup',
      'tech-startup-vibe'
    ];

    for (let i = 0; i < queries.length; i++) {
      const buffer = await this.fetchFromUnsplash(queries[i]);
      if (buffer) {
        const outputPath = path.join(this.backgroundsDir, `${ids[i]}.jpg`);
        await fs.writeFile(outputPath, buffer);
        console.log(`✓ Downloaded: ${ids[i]}.jpg from Unsplash`);
      }
    }
  }

  // Depth layer for atmospheric perspective
  renderDepthLayer(canvas, colorScheme) {
    const { ctx, width, height } = canvas;
    ctx.save();

    // Dark gradient from bottom to create depth
    const depthGradient = ctx.createLinearGradient(0, 0, 0, height);
    const baseColor = colorScheme.primary;
    depthGradient.addColorStop(0, 'rgba(0, 0, 0, 0)');
    depthGradient.addColorStop(0.6, 'rgba(0, 0, 0, 0.1)');
    depthGradient.addColorStop(1, 'rgba(0, 0, 0, 0.3)');

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

  // Mesh overlay for texture
  renderMeshOverlay(canvas, colorScheme) {
    const { ctx, width, height } = canvas;
    ctx.save();
    ctx.globalAlpha = 0.3;

    const gridSize = 40;
    ctx.strokeStyle = canvas.hexToRgba(colorScheme.accent, 0.15);
    ctx.lineWidth = 1;

    // Vertical lines
    for (let x = 0; x < width; x += gridSize) {
      ctx.beginPath();
      ctx.moveTo(x, 0);
      ctx.lineTo(x, height);
      ctx.stroke();
    }

    // Horizontal lines
    for (let y = 0; y < height; y += gridSize) {
      ctx.beginPath();
      ctx.moveTo(0, y);
      ctx.lineTo(width, y);
      ctx.stroke();
    }

    ctx.restore();
  }

  // Light rays (god rays effect)
  renderLightRays(canvas, colorScheme) {
    const { ctx, width, height } = canvas;
    ctx.save();

    // Random angle for light direction
    const angle = Math.random() * Math.PI * 2;
    const rayCount = 5 + Math.floor(Math.random() * 5);

    ctx.globalCompositeOperation = 'screen';
    ctx.globalAlpha = 0.1;

    for (let i = 0; i < rayCount; i++) {
      const rayAngle = angle + (i / rayCount) * Math.PI / 6;
      const rayLength = width * 1.5;

      const gradient = ctx.createLinearGradient(
        width / 2, height / 2,
        width / 2 + Math.cos(rayAngle) * rayLength,
        height / 2 + Math.sin(rayAngle) * rayLength
      );

      gradient.addColorStop(0, canvas.hexToRgba(colorScheme.accent, 0.3));
      gradient.addColorStop(0.5, canvas.hexToRgba(colorScheme.accent, 0.1));
      gradient.addColorStop(1, 'rgba(255, 255, 255, 0)');

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

    ctx.restore();
  }

  // Floating particles with depth
  renderFloatingParticles(canvas, colorScheme) {
    const { ctx, width, height } = canvas;
    ctx.save();

    const particleCount = 80 + Math.floor(Math.random() * 70);
    const colors = [colorScheme.primary, colorScheme.secondary, colorScheme.accent];

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

      // Depth-based sizing (further = smaller)
      const depth = Math.random();
      const size = (1 + Math.random() * 3) * (0.3 + depth * 0.7);
      const alpha = 0.1 + depth * 0.3;

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

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

    ctx.restore();
  }
}

module.exports = BackgroundManager;
