const { createCanvas, loadImage, registerFont } = require('canvas');
const brandConfig = require('../config/brand.json');

class CanvasEngine {
  constructor(width = brandConfig.dimensions.width, height = brandConfig.dimensions.height) {
    this.width = width;
    this.height = height;
    this.canvas = createCanvas(width, height);
    this.ctx = this.canvas.getContext('2d');
    this.layers = [];
  }

  // Clear canvas
  clear() {
    this.ctx.clearRect(0, 0, this.width, this.height);
  }

  // Apply blur effect to entire canvas
  applyBlur(radius) {
    this.ctx.filter = `blur(${radius}px)`;
  }

  // Reset filter
  resetFilter() {
    this.ctx.filter = 'none';
  }

  // Draw gradient background
  drawGradient(colors, angle = 0) {
    const centerX = this.width / 2;
    const centerY = this.height / 2;

    // Convert angle to radians
    const rad = (angle * Math.PI) / 180;

    // Calculate gradient start and end points
    const length = Math.max(this.width, this.height);
    const x1 = centerX + Math.cos(rad) * length / 2;
    const y1 = centerY + Math.sin(rad) * length / 2;
    const x2 = centerX - Math.cos(rad) * length / 2;
    const y2 = centerY - Math.sin(rad) * length / 2;

    const gradient = this.ctx.createLinearGradient(x1, y1, x2, y2);

    // Add color stops
    colors.forEach((color, index) => {
      gradient.addColorStop(index / (colors.length - 1), color);
    });

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

  // Draw mesh gradient (more complex)
  drawMeshGradient(colors) {
    // Create radial gradients from different points
    const positions = [
      { x: 0, y: 0 },
      { x: this.width, y: 0 },
      { x: this.width, y: this.height },
      { x: 0, y: this.height },
      { x: this.width / 2, y: this.height / 2 }
    ];

    this.ctx.globalCompositeOperation = 'screen';

    positions.forEach((pos, index) => {
      const gradient = this.ctx.createRadialGradient(
        pos.x, pos.y, 0,
        pos.x, pos.y, this.width * 0.8
      );

      const color = colors[index % colors.length];
      gradient.addColorStop(0, color + '80'); // 50% opacity
      gradient.addColorStop(1, color + '00'); // Transparent

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

    this.ctx.globalCompositeOperation = 'source-over';
  }

  // Draw solid color background
  drawSolidBackground(color) {
    this.ctx.fillStyle = color;
    this.ctx.fillRect(0, 0, this.width, this.height);
  }

  // Draw overlay (for darkening photos)
  drawOverlay(opacity = 0.4, color = '#000000') {
    this.ctx.fillStyle = color;
    this.ctx.globalAlpha = opacity;
    this.ctx.fillRect(0, 0, this.width, this.height);
    this.ctx.globalAlpha = 1;
  }

  // Draw geometric patterns
  drawGeometricPattern(shape, colors, size = 40, opacity = 0.2) {
    this.ctx.globalAlpha = opacity;

    for (let x = -size; x < this.width + size; x += size) {
      for (let y = -size; y < this.height + size; y += size) {
        const color = colors[Math.floor(Math.random() * colors.length)];
        this.ctx.fillStyle = color;

        if (shape === 'hexagon') {
          this.drawHexagon(x, y, size / 2);
        } else if (shape === 'grid') {
          this.ctx.strokeStyle = color;
          this.ctx.lineWidth = 1;
          this.ctx.strokeRect(x, y, size, size);
        }
      }
    }

    this.ctx.globalAlpha = 1;
  }

  // Draw hexagon helper
  drawHexagon(x, y, radius) {
    this.ctx.beginPath();
    for (let i = 0; i < 6; i++) {
      const angle = (Math.PI / 3) * i;
      const hx = x + radius * Math.cos(angle);
      const hy = y + radius * Math.sin(angle);
      if (i === 0) {
        this.ctx.moveTo(hx, hy);
      } else {
        this.ctx.lineTo(hx, hy);
      }
    }
    this.ctx.closePath();
    this.ctx.fill();
  }

  // Draw wave pattern
  drawWavePattern(colors, amplitude = 50, frequency = 0.02) {
    const gradient = this.ctx.createLinearGradient(0, 0, 0, this.height);
    colors.forEach((color, index) => {
      gradient.addColorStop(index / (colors.length - 1), color);
    });

    this.ctx.fillStyle = gradient;
    this.ctx.beginPath();
    this.ctx.moveTo(0, this.height / 2);

    for (let x = 0; x <= this.width; x++) {
      const y = this.height / 2 + Math.sin(x * frequency) * amplitude;
      this.ctx.lineTo(x, y);
    }

    this.ctx.lineTo(this.width, this.height);
    this.ctx.lineTo(0, this.height);
    this.ctx.closePath();
    this.ctx.fill();
  }

  // Draw particles
  drawParticles(colors, count = 100) {
    this.ctx.globalAlpha = 0.6;

    for (let i = 0; i < count; i++) {
      const x = Math.random() * this.width;
      const y = Math.random() * this.height;
      const radius = Math.random() * 4 + 1;
      const color = colors[Math.floor(Math.random() * colors.length)];

      this.ctx.fillStyle = color;
      this.ctx.beginPath();
      this.ctx.arc(x, y, radius, 0, Math.PI * 2);
      this.ctx.fill();
    }

    this.ctx.globalAlpha = 1;
  }

  // Draw enhanced glass morphism panel with depth and lighting
  drawGlassPanel(x, y, width, height, blurAmount = 10, colorScheme = null, intensity = 'medium') {
    // Save current state
    this.ctx.save();

    // Randomize opacity based on intensity
    const opacities = {
      subtle: { fill: 0.08, border: 0.15, glow: 0.1 },
      medium: { fill: 0.12, border: 0.25, glow: 0.15 },
      high: { fill: 0.18, border: 0.35, glow: 0.25 }
    };
    const opacity = opacities[intensity] || opacities.medium;

    // Create rounded rectangle path
    const radius = 20;
    const createRoundedRect = () => {
      this.ctx.beginPath();
      this.ctx.moveTo(x + radius, y);
      this.ctx.lineTo(x + width - radius, y);
      this.ctx.quadraticCurveTo(x + width, y, x + width, y + radius);
      this.ctx.lineTo(x + width, y + height - radius);
      this.ctx.quadraticCurveTo(x + width, y + height, x + width - radius, y + height);
      this.ctx.lineTo(x + radius, y + height);
      this.ctx.quadraticCurveTo(x, y + height, x, y + height - radius);
      this.ctx.lineTo(x, y + radius);
      this.ctx.quadraticCurveTo(x, y, x + radius, y);
      this.ctx.closePath();
    };

    // Layer 1: Depth shadow (darker background)
    createRoundedRect();
    this.ctx.fillStyle = `rgba(0, 0, 0, ${opacity.fill * 1.5})`;
    this.ctx.fill();

    // Layer 2: Gradient fill (top-to-bottom lighting)
    createRoundedRect();
    const gradient = this.ctx.createLinearGradient(x, y, x, y + height);
    gradient.addColorStop(0, `rgba(255, 255, 255, ${opacity.fill * 1.8})`);
    gradient.addColorStop(0.5, `rgba(255, 255, 255, ${opacity.fill})`);
    gradient.addColorStop(1, `rgba(255, 255, 255, ${opacity.fill * 0.6})`);
    this.ctx.fillStyle = gradient;
    this.ctx.fill();

    // Layer 3: Colored accent glow (if color scheme provided)
    if (colorScheme && colorScheme.accent) {
      createRoundedRect();
      const accentColor = colorScheme.accent;
      const accentGradient = this.ctx.createRadialGradient(
        x + width / 2, y + height / 2, 0,
        x + width / 2, y + height / 2, width / 2
      );
      accentGradient.addColorStop(0, this.hexToRgba(accentColor, opacity.glow));
      accentGradient.addColorStop(0.7, this.hexToRgba(accentColor, opacity.glow * 0.3));
      accentGradient.addColorStop(1, 'rgba(0, 0, 0, 0)');
      this.ctx.fillStyle = accentGradient;
      this.ctx.fill();
    }

    // Layer 4: Outer border
    createRoundedRect();
    this.ctx.strokeStyle = `rgba(255, 255, 255, ${opacity.border})`;
    this.ctx.lineWidth = 2;
    this.ctx.stroke();

    // Layer 5: Inner highlight border (frosted glass effect)
    this.ctx.beginPath();
    const innerRadius = radius - 2;
    this.ctx.moveTo(x + innerRadius + 4, y + 4);
    this.ctx.lineTo(x + width - innerRadius - 4, y + 4);
    this.ctx.quadraticCurveTo(x + width - 4, y + 4, x + width - 4, y + innerRadius + 4);
    this.ctx.lineTo(x + width - 4, y + height - innerRadius - 4);
    this.ctx.quadraticCurveTo(x + width - 4, y + height - 4, x + width - innerRadius - 4, y + height - 4);
    this.ctx.lineTo(x + innerRadius + 4, y + height - 4);
    this.ctx.quadraticCurveTo(x + 4, y + height - 4, x + 4, y + height - innerRadius - 4);
    this.ctx.lineTo(x + 4, y + innerRadius + 4);
    this.ctx.quadraticCurveTo(x + 4, y + 4, x + innerRadius + 4, y + 4);
    this.ctx.closePath();
    this.ctx.strokeStyle = `rgba(255, 255, 255, ${opacity.border * 0.4})`;
    this.ctx.lineWidth = 1;
    this.ctx.stroke();

    // Layer 6: Subtle noise texture for realism
    this.ctx.globalAlpha = 0.02;
    for (let i = 0; i < 50; i++) {
      const nx = x + Math.random() * width;
      const ny = y + Math.random() * height;
      this.ctx.fillStyle = Math.random() > 0.5 ? '#FFFFFF' : '#000000';
      this.ctx.fillRect(nx, ny, 1, 1);
    }
    this.ctx.globalAlpha = 1;

    // Restore state
    this.ctx.restore();
  }

  // Helper: Convert hex color to rgba
  hexToRgba(hex, alpha) {
    const r = parseInt(hex.slice(1, 3), 16);
    const g = parseInt(hex.slice(3, 5), 16);
    const b = parseInt(hex.slice(5, 7), 16);
    return `rgba(${r}, ${g}, ${b}, ${alpha})`;
  }

  // Draw shadow
  drawShadow(x, y, width, height, blur = 30, color = 'rgba(0, 0, 0, 0.3)') {
    this.ctx.shadowColor = color;
    this.ctx.shadowBlur = blur;
    this.ctx.shadowOffsetX = 0;
    this.ctx.shadowOffsetY = 10;

    // Draw invisible rectangle to create shadow
    this.ctx.fillStyle = 'rgba(0, 0, 0, 0)';
    this.ctx.fillRect(x, y, width, height);

    // Reset shadow
    this.ctx.shadowColor = 'transparent';
    this.ctx.shadowBlur = 0;
    this.ctx.shadowOffsetX = 0;
    this.ctx.shadowOffsetY = 0;
  }

  // Draw image with smart scaling
  async drawImage(imagePath, x, y, maxWidth, maxHeight, centerAlign = true) {
    try {
      const img = await loadImage(imagePath);

      // Calculate scaling to fit within maxWidth/maxHeight while maintaining aspect ratio
      const scale = Math.min(maxWidth / img.width, maxHeight / img.height);
      const scaledWidth = img.width * scale;
      const scaledHeight = img.height * scale;

      // Center the image if requested
      const drawX = centerAlign ? x - scaledWidth / 2 : x;
      const drawY = centerAlign ? y - scaledHeight / 2 : y;

      this.ctx.drawImage(img, drawX, drawY, scaledWidth, scaledHeight);

      return { width: scaledWidth, height: scaledHeight, x: drawX, y: drawY };
    } catch (error) {
      console.error('Error loading image:', error);
      return null;
    }
  }

  // Draw image from buffer
  async drawImageFromBuffer(buffer, x, y, maxWidth, maxHeight, centerAlign = true) {
    try {
      const img = await loadImage(buffer);

      const scale = Math.min(maxWidth / img.width, maxHeight / img.height);
      const scaledWidth = img.width * scale;
      const scaledHeight = img.height * scale;

      const drawX = centerAlign ? x - scaledWidth / 2 : x;
      const drawY = centerAlign ? y - scaledHeight / 2 : y;

      this.ctx.drawImage(img, drawX, drawY, scaledWidth, scaledHeight);

      return { width: scaledWidth, height: scaledHeight, x: drawX, y: drawY };
    } catch (error) {
      console.error('Error loading image from buffer:', error);
      return null;
    }
  }

  // Draw text with shadow
  drawText(text, x, y, fontSize, color, fontWeight = 'bold', shadow = true) {
    this.ctx.font = `${fontWeight} ${fontSize}px ${brandConfig.fonts.primary}, ${brandConfig.fonts.fallback}`;
    this.ctx.fillStyle = color;
    this.ctx.textAlign = 'center';
    this.ctx.textBaseline = 'middle';

    if (shadow) {
      this.ctx.shadowColor = 'rgba(0, 0, 0, 0.5)';
      this.ctx.shadowBlur = 10;
      this.ctx.shadowOffsetX = 0;
      this.ctx.shadowOffsetY = 4;
    }

    this.ctx.fillText(text, x, y);

    // Reset shadow
    this.ctx.shadowColor = 'transparent';
    this.ctx.shadowBlur = 0;
    this.ctx.shadowOffsetX = 0;
    this.ctx.shadowOffsetY = 0;
  }

  // Draw VS element
  drawVSElement(vsConfig, x, y, colorScheme) {
    const { type, size, text, fontSize, fontWeight, gradient, glow, borderRadius } = vsConfig;

    this.ctx.save();

    // Draw glow effect if enabled
    if (glow) {
      this.ctx.shadowColor = colorScheme.accent;
      this.ctx.shadowBlur = 30;
    }

    // Draw shape
    if (type === 'circle') {
      if (gradient) {
        const grad = this.ctx.createLinearGradient(x - size/2, y - size/2, x + size/2, y + size/2);
        grad.addColorStop(0, colorScheme.secondary);
        grad.addColorStop(1, colorScheme.primary);
        this.ctx.fillStyle = grad;
      } else {
        this.ctx.fillStyle = colorScheme.primary;
      }

      this.ctx.beginPath();
      this.ctx.arc(x, y, size / 2, 0, Math.PI * 2);
      this.ctx.fill();

      // Border
      this.ctx.strokeStyle = colorScheme.accent;
      this.ctx.lineWidth = 3;
      this.ctx.stroke();

    } else if (type === 'badge' || type === 'square') {
      const halfSize = size / 2;
      const rad = borderRadius || 15;

      if (gradient) {
        const grad = this.ctx.createLinearGradient(x - halfSize, y - halfSize, x + halfSize, y + halfSize);
        grad.addColorStop(0, colorScheme.secondary);
        grad.addColorStop(1, colorScheme.primary);
        this.ctx.fillStyle = grad;
      } else {
        this.ctx.fillStyle = colorScheme.primary;
      }

      // Rounded rectangle
      this.ctx.beginPath();
      this.ctx.moveTo(x - halfSize + rad, y - halfSize);
      this.ctx.lineTo(x + halfSize - rad, y - halfSize);
      this.ctx.quadraticCurveTo(x + halfSize, y - halfSize, x + halfSize, y - halfSize + rad);
      this.ctx.lineTo(x + halfSize, y + halfSize - rad);
      this.ctx.quadraticCurveTo(x + halfSize, y + halfSize, x + halfSize - rad, y + halfSize);
      this.ctx.lineTo(x - halfSize + rad, y + halfSize);
      this.ctx.quadraticCurveTo(x - halfSize, y + halfSize, x - halfSize, y + halfSize - rad);
      this.ctx.lineTo(x - halfSize, y - halfSize + rad);
      this.ctx.quadraticCurveTo(x - halfSize, y - halfSize, x - halfSize + rad, y - halfSize);
      this.ctx.closePath();
      this.ctx.fill();

      // Border
      this.ctx.strokeStyle = colorScheme.accent;
      this.ctx.lineWidth = 3;
      this.ctx.stroke();

    } else if (type === 'hexagon') {
      this.ctx.fillStyle = colorScheme.primary;
      this.ctx.beginPath();
      for (let i = 0; i < 6; i++) {
        const angle = (Math.PI / 3) * i;
        const hx = x + (size / 2) * Math.cos(angle);
        const hy = y + (size / 2) * Math.sin(angle);
        if (i === 0) {
          this.ctx.moveTo(hx, hy);
        } else {
          this.ctx.lineTo(hx, hy);
        }
      }
      this.ctx.closePath();
      this.ctx.fill();

      // Border
      this.ctx.strokeStyle = colorScheme.accent;
      this.ctx.lineWidth = 3;
      this.ctx.stroke();
    }

    // Reset shadow for text
    this.ctx.shadowColor = 'transparent';
    this.ctx.shadowBlur = 0;

    // Draw text
    if (text && type !== 'icon') {
      this.drawText(text, x, y, fontSize, colorScheme.text, fontWeight, false);
    }

    this.ctx.restore();
  }

  // Draw energy burst effect around VS element
  drawEnergyBurst(centerX, centerY, radius, color, intensity = 'medium') {
    this.ctx.save();

    const rings = intensity === 'high' ? 5 : intensity === 'medium' ? 3 : 2;
    const maxRadius = radius * 2;

    for (let i = 0; i < rings; i++) {
      const ringRadius = maxRadius * (i + 1) / rings;
      const alpha = (rings - i) / (rings * 3);

      const gradient = this.ctx.createRadialGradient(
        centerX, centerY, ringRadius * 0.8,
        centerX, centerY, ringRadius
      );
      gradient.addColorStop(0, this.hexToRgba(color, alpha));
      gradient.addColorStop(1, this.hexToRgba(color, 0));

      this.ctx.fillStyle = gradient;
      this.ctx.beginPath();
      this.ctx.arc(centerX, centerY, ringRadius, 0, Math.PI * 2);
      this.ctx.fill();
    }

    this.ctx.restore();
  }

  // Draw lightning bolt effect
  drawLightningBolt(startX, startY, endX, endY, color, branches = 3) {
    this.ctx.save();
    this.ctx.strokeStyle = color;
    this.ctx.lineWidth = 3;
    this.ctx.shadowBlur = 20;
    this.ctx.shadowColor = color;

    const drawBolt = (sx, sy, ex, ey, depth = 0) => {
      if (depth > 2) return;

      const midX = (sx + ex) / 2 + (Math.random() - 0.5) * 40;
      const midY = (sy + ey) / 2 + (Math.random() - 0.5) * 40;

      this.ctx.beginPath();
      this.ctx.moveTo(sx, sy);
      this.ctx.lineTo(midX, midY);
      this.ctx.lineTo(ex, ey);
      this.ctx.stroke();

      // Recursive branches
      if (depth < 2 && Math.random() > 0.5) {
        const branchEndX = midX + (Math.random() - 0.5) * 60;
        const branchEndY = midY + (Math.random() - 0.5) * 60;
        drawBolt(midX, midY, branchEndX, branchEndY, depth + 1);
      }
    };

    for (let i = 0; i < branches; i++) {
      const offsetX = (Math.random() - 0.5) * 20;
      const offsetY = (Math.random() - 0.5) * 20;
      drawBolt(startX + offsetX, startY + offsetY, endX + offsetX, endY + offsetY, 0);
    }

    this.ctx.restore();
  }

  // Draw particle burst effect
  drawParticleBurst(centerX, centerY, count, colors, radius) {
    this.ctx.save();

    for (let i = 0; i < count; i++) {
      const angle = (Math.PI * 2 * i) / count;
      const distance = radius * (0.8 + Math.random() * 0.4);
      const px = centerX + Math.cos(angle) * distance;
      const py = centerY + Math.sin(angle) * distance;
      const size = 2 + Math.random() * 4;

      const color = colors[Math.floor(Math.random() * colors.length)];
      const gradient = this.ctx.createRadialGradient(px, py, 0, px, py, size);
      gradient.addColorStop(0, this.hexToRgba(color, 0.8));
      gradient.addColorStop(1, this.hexToRgba(color, 0));

      this.ctx.fillStyle = gradient;
      this.ctx.beginPath();
      this.ctx.arc(px, py, size, 0, Math.PI * 2);
      this.ctx.fill();
    }

    this.ctx.restore();
  }

  // Draw energy lines connecting VS to logos
  drawEnergyLines(centerX, centerY, targets, color) {
    this.ctx.save();

    targets.forEach(target => {
      this.ctx.strokeStyle = this.hexToRgba(color, 0.3);
      this.ctx.lineWidth = 2;
      this.ctx.shadowBlur = 15;
      this.ctx.shadowColor = color;

      // Draw wavy line
      this.ctx.beginPath();
      this.ctx.moveTo(centerX, centerY);

      const steps = 20;
      const dx = (target.x - centerX) / steps;
      const dy = (target.y - centerY) / steps;

      for (let i = 1; i <= steps; i++) {
        const x = centerX + dx * i;
        const y = centerY + dy * i;
        const wave = Math.sin(i * 0.5) * 5;
        this.ctx.lineTo(x + wave, y);
      }

      this.ctx.stroke();
    });

    this.ctx.restore();
  }

  // Draw chromatic aberration effect
  drawChromaticAberration(x, y, size, colorScheme, offset = 3) {
    this.ctx.save();

    // Red channel
    this.ctx.globalCompositeOperation = 'screen';
    this.ctx.fillStyle = this.hexToRgba('#FF0000', 0.3);
    this.ctx.beginPath();
    this.ctx.arc(x - offset, y, size / 2, 0, Math.PI * 2);
    this.ctx.fill();

    // Green channel
    this.ctx.fillStyle = this.hexToRgba('#00FF00', 0.3);
    this.ctx.beginPath();
    this.ctx.arc(x, y, size / 2, 0, Math.PI * 2);
    this.ctx.fill();

    // Blue channel
    this.ctx.fillStyle = this.hexToRgba('#0000FF', 0.3);
    this.ctx.beginPath();
    this.ctx.arc(x + offset, y, size / 2, 0, Math.PI * 2);
    this.ctx.fill();

    this.ctx.restore();
  }

  // Get canvas buffer
  toBuffer(format = 'image/png') {
    return this.canvas.toBuffer(format);
  }

  // Get data URL
  toDataURL(format = 'image/png') {
    return this.canvas.toDataURL(format);
  }
}

module.exports = CanvasEngine;
