#!/usr/bin/env node
import fs from 'fs';
import os from 'os';
import path from 'path';
import { execFileSync } from 'child_process';
import { fileURLToPath } from 'url';

const __dirname = path.dirname(fileURLToPath(import.meta.url));
const projectRoot = path.resolve(__dirname, '..');
const iconsDir = path.join(projectRoot, 'build', 'icons');
const publicAssetsDir = path.join(projectRoot, 'public', 'assets');
const sourcePngPath = path.join(publicAssetsDir, 'vlcode-lite-source.png');
const svgPath = path.join(iconsDir, 'vlcode-lite.svg');
const icnsPath = path.join(iconsDir, 'vlcode-lite.icns');
const publicSvgPath = path.join(publicAssetsDir, 'vlcode-lite-icon.svg');
const publicPngPath = path.join(publicAssetsDir, 'vlcode-lite-icon.png');
const publicFavicon32Path = path.join(publicAssetsDir, 'vlcode-lite-favicon-32.png');
const publicFavicon16Path = path.join(publicAssetsDir, 'vlcode-lite-favicon-16.png');
const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'vlcode-icon-'));
const iconsetDir = path.join(tempDir, 'vlcode-lite.iconset');

const iconSizes = [
  { size: 16, scale: 1 },
  { size: 16, scale: 2 },
  { size: 32, scale: 1 },
  { size: 32, scale: 2 },
  { size: 128, scale: 1 },
  { size: 128, scale: 2 },
  { size: 256, scale: 1 },
  { size: 256, scale: 2 },
  { size: 512, scale: 1 },
  { size: 512, scale: 2 },
];

function run(command, args) {
  execFileSync(command, args, { stdio: 'inherit' });
}

function readImageSize(filePath) {
  const output = execFileSync('sips', ['-g', 'pixelWidth', '-g', 'pixelHeight', filePath], { encoding: 'utf8' });
  const width = Number(output.match(/pixelWidth:\s*(\d+)/)?.[1] || 0);
  const height = Number(output.match(/pixelHeight:\s*(\d+)/)?.[1] || 0);
  if (!width || !height) {
    throw new Error(`Could not determine image dimensions for ${filePath}`);
  }
  return { width, height };
}

function buildSvgFromPng(pngPath) {
  const canvasSize = 1024;
  const panelInset = 44;
  const panelSize = canvasSize - panelInset * 2;
  const panelRadius = 232;
  const pngBase64 = fs.readFileSync(pngPath).toString('base64');
  const { width, height } = readImageSize(pngPath);
  const maxWidth = 900;
  const maxHeight = 672;
  const scale = Math.min(maxWidth / width, maxHeight / height);
  const drawWidth = Math.round(width * scale);
  const drawHeight = Math.round(height * scale);
  const x = Math.round((canvasSize - drawWidth) / 2);
  const y = Math.round((canvasSize - drawHeight) / 2);

  return `<svg width="${canvasSize}" height="${canvasSize}" viewBox="0 0 ${canvasSize} ${canvasSize}" fill="none" xmlns="http://www.w3.org/2000/svg">
  <defs>
    <linearGradient id="bg" x1="120" y1="72" x2="912" y2="968" gradientUnits="userSpaceOnUse">
      <stop stop-color="#081018"/>
      <stop offset="1" stop-color="#0C1724"/>
    </linearGradient>
    <radialGradient id="glow" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(512 288) rotate(90) scale(560 660)">
      <stop stop-color="#3C9BFF" stop-opacity="0.32"/>
      <stop offset="0.56" stop-color="#39C8D6" stop-opacity="0.14"/>
      <stop offset="1" stop-color="#39C8D6" stop-opacity="0"/>
    </radialGradient>
    <linearGradient id="shine" x1="200" y1="124" x2="704" y2="652" gradientUnits="userSpaceOnUse">
      <stop stop-color="#FFFFFF" stop-opacity="0.10"/>
      <stop offset="0.42" stop-color="#FFFFFF" stop-opacity="0.02"/>
      <stop offset="1" stop-color="#FFFFFF" stop-opacity="0"/>
    </linearGradient>
    <filter id="shadow" x="0" y="0" width="${canvasSize}" height="${canvasSize}" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
      <feDropShadow dx="0" dy="22" stdDeviation="26" flood-color="#03060C" flood-opacity="0.42"/>
    </filter>
    <filter id="logoMaskFilter" x="0" y="0" width="${canvasSize}" height="${canvasSize}" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
      <feColorMatrix in="SourceGraphic" type="matrix" values="
        0 0 0 0 0
        0 0 0 0 0
        0 0 0 0 0
        3 3 3 0 -0.35
      "/>
    </filter>
    <clipPath id="panel">
      <rect x="${panelInset}" y="${panelInset}" width="${panelSize}" height="${panelSize}" rx="${panelRadius}"/>
    </clipPath>
    <mask id="logoMask" x="${x}" y="${y}" width="${drawWidth}" height="${drawHeight}" maskUnits="userSpaceOnUse" maskContentUnits="userSpaceOnUse" style="mask-type:alpha">
      <image href="data:image/png;base64,${pngBase64}" x="${x}" y="${y}" width="${drawWidth}" height="${drawHeight}" preserveAspectRatio="xMidYMid meet" filter="url(#logoMaskFilter)"/>
    </mask>
  </defs>

  <g clip-path="url(#panel)">
    <rect x="${panelInset}" y="${panelInset}" width="${panelSize}" height="${panelSize}" rx="${panelRadius}" fill="url(#bg)"/>
    <rect x="${panelInset}" y="${panelInset}" width="${panelSize}" height="${panelSize}" rx="${panelRadius}" fill="url(#glow)"/>
    <rect x="${panelInset}" y="${panelInset}" width="${panelSize}" height="${panelSize}" rx="${panelRadius}" fill="url(#shine)"/>
    <g filter="url(#shadow)">
      <image href="data:image/png;base64,${pngBase64}" x="${x}" y="${y}" width="${drawWidth}" height="${drawHeight}" preserveAspectRatio="xMidYMid meet" mask="url(#logoMask)"/>
    </g>
  </g>
</svg>
`;
}

function findRenderedPng(outputDir) {
  const matches = fs.readdirSync(outputDir)
    .filter((entry) => entry.endsWith('.png'))
    .map((entry) => path.join(outputDir, entry));
  if (matches.length === 0) {
    throw new Error('Quick Look did not produce a PNG preview for the SVG icon');
  }
  return matches[0];
}

try {
  fs.mkdirSync(iconsDir, { recursive: true });
  fs.mkdirSync(publicAssetsDir, { recursive: true });

  if (fs.existsSync(sourcePngPath)) {
    fs.writeFileSync(svgPath, buildSvgFromPng(sourcePngPath), 'utf8');
  }

  if (!fs.existsSync(svgPath)) {
    throw new Error(`Missing source SVG: ${svgPath}`);
  }

  fs.copyFileSync(svgPath, publicSvgPath);
  fs.mkdirSync(iconsetDir, { recursive: true });

  run('qlmanage', ['-t', '-s', '1024', '-o', tempDir, svgPath]);
  const basePng = findRenderedPng(tempDir);
  fs.copyFileSync(basePng, publicPngPath);
  run('sips', ['-z', '32', '32', basePng, '--out', publicFavicon32Path]);
  run('sips', ['-z', '16', '16', basePng, '--out', publicFavicon16Path]);

  for (const icon of iconSizes) {
    const pixels = icon.size * icon.scale;
    const suffix = icon.scale === 2 ? '@2x' : '';
    const outputPath = path.join(iconsetDir, `icon_${icon.size}x${icon.size}${suffix}.png`);
    run('sips', ['-z', String(pixels), String(pixels), basePng, '--out', outputPath]);
  }

  fs.rmSync(icnsPath, { force: true });
  run('iconutil', ['-c', 'icns', iconsetDir, '-o', icnsPath]);
  console.log(`[build-icon] Wrote ${svgPath}`);
  console.log(`[build-icon] Wrote ${publicSvgPath}`);
  console.log(`[build-icon] Wrote ${publicPngPath}`);
  console.log(`[build-icon] Wrote ${publicFavicon32Path}`);
  console.log(`[build-icon] Wrote ${publicFavicon16Path}`);
  console.log(`[build-icon] Wrote ${icnsPath}`);
} finally {
  fs.rmSync(tempDir, { recursive: true, force: true });
}
