import { execFileSync } from 'node:child_process';
import fs from 'node:fs';
import path from 'node:path';
import { fileURLToPath } from 'node:url';

import { build } from 'esbuild';

import { resolveIsProduction, resolveObfuscateMain } from './build-env.mjs';

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const root = path.resolve(__dirname, '..');

const isProd = resolveIsProduction();
const obfuscateMain = resolveObfuscateMain();

/** База для `GET …/v1/status` (отзыв). Прод: по умолчанию публичный сервер; переопределение: `DND_LICENSE_STATUS_URL=… npm run build`. */
const DEFAULT_LICENSE_STATUS_BASE = 'https://license.ttrpgplayer.ru/';

/** Старые .map от dev-сборок не должны попадать в pack. */
function removeStaleNodeBundleMaps() {
  for (const p of [
    path.join(root, 'dist/main/index.cjs.map'),
    path.join(root, 'dist/preload/index.cjs.map'),
  ]) {
    if (fs.existsSync(p)) fs.unlinkSync(p);
  }
}

function runViteBuild() {
  const cmd = isProd ? 'npx vite build' : 'npx vite build --mode development';
  execFileSync(cmd, {
    cwd: root,
    stdio: 'inherit',
    shell: true,
    env: {
      ...process.env,
      NODE_ENV: isProd ? 'production' : 'development',
    },
  });
}

async function buildNodeTargets() {
  if (isProd) removeStaleNodeBundleMaps();

  const nodeEnvLiteral = JSON.stringify(isProd ? 'production' : 'development');
  const licenseStatusFromEnv = process.env.DND_LICENSE_STATUS_URL?.trim();
  const licenseStatusBase =
    isProd && (licenseStatusFromEnv || DEFAULT_LICENSE_STATUS_BASE)
      ? (licenseStatusFromEnv || DEFAULT_LICENSE_STATUS_BASE).replace(/\/+$/u, '') + '/'
      : null;
  const define = {
    'process.env.NODE_ENV': nodeEnvLiteral,
    ...(licenseStatusBase
      ? { 'process.env.DND_LICENSE_STATUS_URL': JSON.stringify(licenseStatusBase) }
      : {}),
  };
  const common = {
    platform: 'node',
    target: 'node22',
    format: 'cjs',
    bundle: true,
    minify: isProd,
    sourcemap: !isProd,
    external: ['electron', 'electron-updater', 'sharp', 'ffmpeg-static', 'classic-level'],
    define,
    drop: isProd ? ['console', 'debugger'] : [],
  };

  const mainOut = path.join(root, 'dist/main/index.cjs');

  await build({
    ...common,
    entryPoints: [path.join(root, 'app/main/index.ts')],
    outfile: mainOut,
  });

  if (isProd && obfuscateMain) {
    const { obfuscateMainBundleFile } = await import('./obfuscate-main.mjs');
    obfuscateMainBundleFile(mainOut);
  }

  await build({
    ...common,
    entryPoints: [path.join(root, 'app/preload/index.ts')],
    outfile: path.join(root, 'dist/preload/index.cjs'),
  });
}

await buildNodeTargets();
execFileSync('node', [path.join(root, 'scripts', 'gen-window-icon.mjs')], {
  cwd: root,
  stdio: 'inherit',
});
runViteBuild();

// Тот же PNG, что electron-builder кладёт в .exe/.app — в рантайме для окна/дока (паритет с Windows).
const packIcon = path.join(root, 'build', 'icon.png');
const distPackIcon = path.join(root, 'dist', 'renderer', 'app-pack-icon.png');
if (fs.existsSync(packIcon)) {
  fs.copyFileSync(packIcon, distPackIcon);
  console.log('copied pack icon to', distPackIcon);
}
