#!/usr/bin/env node

/**
 * PWA Icon Generator for Workout App
 * Generates PNG icons without external dependencies
 * Uses only Node.js built-in modules (fs, zlib, path)
 */

const fs = require('fs');
const path = require('path');
const zlib = require('zlib');

// Configuration
const BACKGROUND_COLOR = { r: 10, g: 10, b: 10 }; // #0A0A0A
const TEXT_COLOR = { r: 255, g: 255, b: 255 }; // White
const ICON_SIZES = [72, 96, 128, 144, 152, 192, 384, 512];
const MASKABLE_SIZES = [192, 512];

const OUTPUT_DIR = path.join(__dirname, '..', 'public', 'icons');

/**
 * Create output directory if it doesn't exist
 */
function ensureOutputDir() {
  if (!fs.existsSync(OUTPUT_DIR)) {
    fs.mkdirSync(OUTPUT_DIR, { recursive: true });
  }
}

/**
 * Draw a simple white kettlebell on black background.
 */
function drawKettlebell(buffer, width, height) {
  const canvasWidth = width;
  const canvasHeight = height;

  // Helper to set a pixel
  const setPixel = (x, y, r, g, b, a = 255) => {
    if (x < 0 || x >= canvasWidth || y < 0 || y >= canvasHeight) return;
    const idx = (y * canvasWidth + x) * 4;
    buffer[idx] = r;
    buffer[idx + 1] = g;
    buffer[idx + 2] = b;
    buffer[idx + 3] = a;
  };

  // Helper to draw a filled rectangle (fast)
  const fillRect = (x, y, w, h, r, g, b) => {
    const x0 = Math.max(0, Math.floor(x));
    const y0 = Math.max(0, Math.floor(y));
    const x1 = Math.min(canvasWidth, Math.ceil(x + w));
    const y1 = Math.min(canvasHeight, Math.ceil(y + h));

    for (let yi = y0; yi < y1; yi++) {
      for (let xi = x0; xi < x1; xi++) {
        setPixel(xi, yi, r, g, b);
      }
    }
  };

  // Fill background
  fillRect(0, 0, canvasWidth, canvasHeight, BACKGROUND_COLOR.r, BACKGROUND_COLOR.g, BACKGROUND_COLOR.b);

  const cx = canvasWidth / 2;
  const bodyTop = Math.floor(canvasHeight * 0.34);
  const bodyBottom = Math.floor(canvasHeight * 0.86);
  const bodyHalfWidth = canvasWidth * 0.27;

  const handleOuterRadius = canvasWidth * 0.2;
  const handleInnerRadius = canvasWidth * 0.11;
  const handleCenterY = canvasHeight * 0.35;

  // Draw ring handle (outer white circle, inner black circle).
  for (let y = 0; y < canvasHeight; y++) {
    for (let x = 0; x < canvasWidth; x++) {
      const dx = x - cx;
      const dy = y - handleCenterY;
      const dist = Math.sqrt(dx * dx + dy * dy);
      if (dist <= handleOuterRadius && dist >= handleInnerRadius) {
        setPixel(x, y, TEXT_COLOR.r, TEXT_COLOR.g, TEXT_COLOR.b);
      }
    }
  }

  // Handle connectors.
  const connectorWidth = Math.floor(canvasWidth * 0.06);
  const connectorHeight = Math.floor(canvasHeight * 0.1);
  const leftConnectorX = Math.floor(cx - handleOuterRadius - connectorWidth * 0.2);
  const rightConnectorX = Math.floor(cx + handleOuterRadius - connectorWidth * 0.8);
  const connectorY = Math.floor(canvasHeight * 0.39);
  fillRect(leftConnectorX, connectorY, connectorWidth, connectorHeight, TEXT_COLOR.r, TEXT_COLOR.g, TEXT_COLOR.b);
  fillRect(rightConnectorX, connectorY, connectorWidth, connectorHeight, TEXT_COLOR.r, TEXT_COLOR.g, TEXT_COLOR.b);

  // Rounded-ish body made from stacked horizontal bars.
  const bodyHeight = bodyBottom - bodyTop;
  for (let i = 0; i < bodyHeight; i++) {
    const t = i / bodyHeight;
    const curve = 1 - Math.pow((t - 0.5) * 2, 2); // widest in middle
    const half = bodyHalfWidth * (0.78 + 0.22 * Math.max(0, curve));
    const y = bodyTop + i;
    const x = Math.floor(cx - half);
    const w = Math.ceil(half * 2);
    fillRect(x, y, w, 1, TEXT_COLOR.r, TEXT_COLOR.g, TEXT_COLOR.b);
  }

  // Flat base accent.
  const baseWidth = Math.floor(canvasWidth * 0.42);
  const baseHeight = Math.max(1, Math.floor(canvasHeight * 0.035));
  fillRect(Math.floor(cx - baseWidth / 2), bodyBottom - baseHeight, baseWidth, baseHeight, TEXT_COLOR.r, TEXT_COLOR.g, TEXT_COLOR.b);
}

/**
 * Create a PNG file from raw pixel data
 * Uses PNG file format with zlib compression
 */
function createPNG(width, height, pixelBuffer, outputPath) {
  // PNG signature
  const pngSignature = Buffer.from([137, 80, 78, 71, 13, 10, 26, 10]);

  // IHDR chunk (image header)
  const ihdrData = Buffer.alloc(13);
  ihdrData.writeUInt32BE(width, 0);
  ihdrData.writeUInt32BE(height, 4);
  ihdrData[8] = 8; // bit depth
  ihdrData[9] = 6; // color type (RGBA)
  ihdrData[10] = 0; // compression method
  ihdrData[11] = 0; // filter method
  ihdrData[12] = 0; // interlace method

  const ihdr = createChunk('IHDR', ihdrData);

  // IDAT chunk (image data)
  // Each row needs a filter byte (0 = None)
  const rawData = Buffer.alloc(height * (1 + width * 4));
  for (let y = 0; y < height; y++) {
    rawData[y * (1 + width * 4)] = 0; // filter type
    const rowStart = y * (1 + width * 4) + 1;
    pixelBuffer.copy(rawData, rowStart, y * width * 4, (y + 1) * width * 4);
  }

  const compressed = zlib.deflateSync(rawData);
  const idat = createChunk('IDAT', compressed);

  // IEND chunk (image end)
  const iend = createChunk('IEND', Buffer.alloc(0));

  // Combine all chunks
  const png = Buffer.concat([pngSignature, ihdr, idat, iend]);

  fs.writeFileSync(outputPath, png);
}

/**
 * Create a PNG chunk with proper CRC
 */
function createChunk(type, data) {
  const length = Buffer.alloc(4);
  length.writeUInt32BE(data.length, 0);

  const typeBuffer = Buffer.from(type, 'ascii');
  const chunkData = Buffer.concat([typeBuffer, data]);

  // Calculate CRC32
  const crc = calculateCRC32(chunkData);
  const crcBuffer = Buffer.alloc(4);
  crcBuffer.writeUInt32BE(crc, 0);

  return Buffer.concat([length, chunkData, crcBuffer]);
}

/**
 * Calculate CRC32 checksum for PNG chunks
 */
function calculateCRC32(data) {
  const table = [];
  for (let n = 0; n < 256; n++) {
    let c = n;
    for (let k = 0; k < 8; k++) {
      c = c & 1 ? 0xedb88320 ^ (c >>> 1) : c >>> 1;
    }
    table[n] = c >>> 0;
  }

  let crc = 0xffffffff;
  for (let i = 0; i < data.length; i++) {
    crc = table[(crc ^ data[i]) & 0xff] ^ (crc >>> 8);
  }
  return (crc ^ 0xffffffff) >>> 0;
}

/**
 * Generate all icon sizes
 */
function generateIcons() {
  ensureOutputDir();

  console.log('Generating PWA icons for Workout App...\n');

  ICON_SIZES.forEach((size) => {
    // Regular icon
    const buffer = Buffer.alloc(size * size * 4);
    drawKettlebell(buffer, size, size);

    const outputPath = path.join(OUTPUT_DIR, `icon-${size}x${size}.png`);
    createPNG(size, size, buffer, outputPath);
    console.log(`✓ Created ${path.basename(outputPath)}`);

    // Maskable variant (for adaptive icons on Android)
    if (MASKABLE_SIZES.includes(size)) {
      const maskableBuffer = Buffer.alloc(size * size * 4);
      drawKettlebell(maskableBuffer, size, size);

      const maskablePath = path.join(OUTPUT_DIR, `icon-${size}x${size}-maskable.png`);
      createPNG(size, size, maskableBuffer, maskablePath);
      console.log(`✓ Created ${path.basename(maskablePath)}`);
    }
  });

  // Create a matching favicon SVG as well.
  const svgPath = path.join(OUTPUT_DIR, 'favicon.svg');
  const svgContent = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 192 192">
  <rect width="192" height="192" fill="#0A0A0A"/>
  <circle cx="96" cy="66" r="38" fill="none" stroke="#fff" stroke-width="18"/>
  <rect x="52" y="69" width="18" height="22" fill="#fff"/>
  <rect x="122" y="69" width="18" height="22" fill="#fff"/>
  <path d="M 43 77 C 52 62, 140 62, 149 77 L 149 150 C 149 163, 131 170, 96 170 C 61 170, 43 163, 43 150 Z" fill="#fff"/>
</svg>`;
  fs.writeFileSync(svgPath, svgContent);
  console.log(`✓ Created ${path.basename(svgPath)}`);

  console.log(`\nAll icons generated successfully in ${OUTPUT_DIR}`);
}

// Run the generator
generateIcons();
