// ============================================================
// build.mjs — 构建总管
//
// 用法：node build.mjs [选项]
//
// 平台（必选其一）：
//   --win            Windows
//   --mac            macOS
//   --linux          Linux
//
// 操作（可选组合，默认只执行 --build）：
//   --build          仅构建（默认）
//   --clean          构建前清理 release/ dist/ dist-electron/
//   --sign           代码签名
//   --upload         上传安装包到 OSS
//   --publish        发布版本信息到后端 API
//   --all            全流程（clean + build + sign + upload + publish）
//
// 签名（仅 --sign 时可用）：
//   --cert <path>        证书文件路径 (.pfx)
//   --cert-password <p>  证书密码
//
// 示例：
//   node build.mjs --win                              # 仅打包
//   node build.mjs --win --upload --publish           # 打包 + 上传 + 发布
//   node build.mjs --win --all                        # 全流程
//   node build.mjs --win --sign --cert ./cert.pfx --cert-password xxx
// ============================================================

import { spawn } from 'node:child_process';
import { readFileSync } from 'node:fs';
import { join, dirname } from 'node:path';
import { fileURLToPath } from 'node:url';

const __dirname = dirname(fileURLToPath(import.meta.url));
const ROOT = __dirname;

// ANSI 颜色工具（在其它代码之前定义，因为 printHelp() 在参数解析时就会调用）
const c = (code, text) => `\x1b[${code}m${text}\x1b[0m`;
const dim  = (t) => c(2, t);
const bold = (t) => c(1, t);
const cyan = (t) => c(36, t);
const green = (t) => c(32, t);
const yellow = (t) => c(33, t);

// ---------- 参数解析 ----------

const args = process.argv.slice(2);

const opts = {
  win: false,
  mac: false,
  linux: false,
  clean: false,
  build: false,
  sign: false,
  upload: false,
  publish: false,
  cert: '',
  certPassword: '',
};

let i = 0;
while (i < args.length) {
  const a = args[i];
  switch (a) {
    case '--win':       opts.win = true; break;
    case '--mac':       opts.mac = true; break;
    case '--linux':     opts.linux = true; break;
    case '--clean':     opts.clean = true; break;
    case '--build':     opts.build = true; break;
    case '--sign':      opts.sign = true; break;
    case '--upload':    opts.upload = true; break;
    case '--publish':   opts.publish = true; break;
    case '--all':
      opts.clean = opts.build = opts.sign = opts.upload = opts.publish = true;
      break;
    case '--cert':
      opts.cert = args[++i] || '';
      break;
    case '--cert-password':
      opts.certPassword = args[++i] || '';
      break;
    case '--help':   // fallthrough
    case '-h':
      printHelp();
      process.exit(0);
      break;        // eslint 友好
    default:
      // 忽略未知参数
      break;
  }
  i++;
}

// ---------- 校验 ----------

const platformCount = [opts.win, opts.mac, opts.linux].filter(Boolean).length;
if (platformCount !== 1) {
  console.error('错误: 请指定且仅指定一个平台（--win / --mac / --linux）');
  process.exit(1);
}

// 默认执行 build
if (!opts.clean && !opts.build && !opts.sign && !opts.upload && !opts.publish) {
  opts.build = true;
}

const platform = opts.win ? 'win32' : opts.mac ? 'darwin' : 'linux';

const pkg = JSON.parse(readFileSync(join(ROOT, 'package.json'), 'utf-8'));
const version = pkg.version;

// ---------- 工具函数 ----------

function run(cmd, args, opts = {}) {
  return new Promise((resolve, reject) => {
    const child = spawn(cmd, args, {
      cwd: ROOT,
      stdio: 'inherit',
      shell: true,
      ...opts,
      env: { ...process.env, ...(opts.env || {}) },
    });
    child.on('close', (code) => {
      if (code === 0) resolve();
      else reject(new Error(`${cmd} ${args.join(' ')} 退出码: ${code}`));
    });
    child.on('error', reject);
  });
}

function runScript(name, ...args) {
  const scriptPath = join(ROOT, 'scripts', `${name}.mjs`);
  return run('node', [scriptPath, ...args]);
}

function step(title) {
  console.log(`\n${'='.repeat(60)}`);
  console.log(`  ${title}`);
  console.log(`${'='.repeat(60)}\n`);
}

// ---------- 主流程 ----------

async function main() {
  const electronBuilderPlatform = opts.win ? '--win' : opts.mac ? '--mac' : '--linux';

  console.log('┌──────────────────────────────────────┐');
  console.log(`│  HeiXiu 构建 v${version}  ${platform}`.padEnd(45) + '│');
  console.log('└──────────────────────────────────────┘');
  console.log(`操作: ${[
    opts.clean && '清理',
    opts.build && '构建',
    opts.sign && '签名',
    opts.upload && '上传',
    opts.publish && '发布',
  ].filter(Boolean).join(' → ')}`);

  // ── Step 1: 清理 ──
  if (opts.clean) {
    step('1/ 清理构建产物');
    await runScript('clean');
  }

  // ── Step 2: 构建 ──
  if (opts.build) {
    step('2/ 构建应用');

    // 签名环境变量（electron-builder 原生支持 CSC_LINK / CSC_KEY_PASSWORD）
    const signEnv = {};
    if (opts.sign) {
      if (opts.cert) signEnv.CSC_LINK = opts.cert;
      if (opts.certPassword) signEnv.CSC_KEY_PASSWORD = opts.certPassword;
      console.log(opts.cert ? `签名证书: ${opts.cert}` : '签名: 使用系统证书存储');
    }

    // 2a. TypeScript 编译
    console.log('[tsc] 类型检查...');
    await run('npx', ['tsc']);

    // 2b. Vite 构建
    console.log('[vite] 打包前端 + Electron...');
    await run('npx', ['vite', 'build']);

    // 2c. electron-builder 打包
    console.log(`[electron-builder] ${electronBuilderPlatform} 打包...`);
    await run('npx', ['electron-builder', electronBuilderPlatform], {
      env: { ...signEnv },
    });

    // 2d. 生成 update-info.json
    console.log('[info] 生成 update-info.json...');
    await runScript('generate-update-info', platform, version);
  }

  // ── Step 3: 上传 OSS ──
  if (opts.upload) {
    step('3/ 上传 OSS');
    await runScript('upload-oss', platform, version);
  }

  // ── Step 4: 发布到 API ──
  if (opts.publish) {
    step('4/ 发布版本到 API');
    await runScript('publish-release', platform, version);
  }

  console.log('\n✅ 全部完成');
}

function printHelp() {
  const W = 62;
  const box = (title) => {
    const pad = Math.max(0, W - 4 - title.length);
    console.log(`\n${cyan('┌')}${cyan('─'.repeat(W - 2))}${cyan('┐')}`);
    console.log(`${cyan('│')}  ${bold(title)}${' '.repeat(pad)}${cyan('│')}`);
    console.log(`${cyan('└')}${cyan('─'.repeat(W - 2))}${cyan('┘')}`);
  };
  const row = (flag, desc) => {
    console.log(`  ${green(flag.padEnd(22))}${dim(desc)}`);
  };
  const hdr = (t) => console.log(`\n  ${bold(yellow(t))}`);

  console.log('');
  console.log(cyan('  ╔') + cyan('═══════════════════════════════════════════════════') + cyan('╗'));
  console.log(cyan('  ║') + bold('   船长·HeiXiu — 构建工具') + '                          ' + cyan('║'));
  console.log(cyan('  ╚') + cyan('═══════════════════════════════════════════════════') + cyan('╝'));

  // 用法
  box('用法');
  console.log(`  ${bold('node build.mjs')} ${dim('<平台> [版本] [操作...]')}`);
  console.log(`  ${bold('npm run build:win')}  ${dim('— 等效快捷命令')}`);

  // 平台
  hdr('平台（必选其一）');
  row('--win',   'Windows');
  row('--mac',   'macOS');
  row('--linux', 'Linux');

  // 操作
  hdr('操作（可选组合，不指定则默认 --build）');
  row('--build',   '构建应用（tsc + vite + electron-builder + info）');
  row('--clean',   '构建前清理 release/ dist/ dist-electron/');
  row('--sign',    '代码签名（需配合 --cert 或环境变量）');
  row('--upload',  '上传安装包到 OSS');
  row('--publish', '发布版本信息到后端 API');
  row('--all',     '全流程 = clean + build + sign + upload + publish');

  // 签名
  hdr('签名参数（配合 --sign）');
  row('--cert <path>',       '证书文件路径（.pfx / .p12）');
  row('--cert-password <p>', '证书密码');
  console.log(`  ${dim('也可通过 CSC_LINK / CSC_KEY_PASSWORD 环境变量设置')}`);

  // 示例
  box('示例');
  console.log(`  ${dim('# 日常构建')}`);
  console.log(`  ${bold('node build.mjs --win')}`);
  console.log(`  ${bold('npm run build:win')}                  ${dim('— 等效')}`);
  console.log('');
  console.log(`  ${dim('# 打包 + 上传 OSS + 发布到 API')}`);
  console.log(`  ${bold('node build.mjs --win --upload --publish')}`);
  console.log('');
  console.log(`  ${dim('# 全流程（清理 → 构建 → 签名 → 上传 → 发布）')}`);
  console.log(`  ${bold('node build.mjs --win --all --cert ./cert.pfx --cert-password xxx')}`);
  console.log('');
  console.log(`  ${dim('# 仅清理')}`);
  console.log(`  ${bold('npm run build:clean')}`);

  // 环境变量
  box('环境变量');
  console.log(`  ${yellow('UPDATE_API_URL')}         ${dim('版本检查 API 基地址')}`);
  console.log(`  ${yellow('UPDATE_API_KEY')}         ${dim('发布 API 鉴权 Key')}`);
  console.log(`  ${yellow('UPDATE_DOWNLOAD_BASE')}   ${dim('OSS 下载基地址（预判 URL 用）')}`);
  console.log(`  ${yellow('OSS_ENDPOINT')}           ${dim('阿里云 OSS endpoint')}`);
  console.log(`  ${yellow('OSS_BUCKET')}             ${dim('阿里云 OSS bucket 名称')}`);
  console.log(`  ${yellow('OSS_ACCESS_KEY_ID')}      ${dim('阿里云 AccessKey ID')}`);
  console.log(`  ${yellow('OSS_ACCESS_KEY_SECRET')}  ${dim('阿里云 AccessKey Secret')}`);
  console.log(`  ${yellow('CSC_LINK')}               ${dim('签名证书路径（与 --cert 等效）')}`);
  console.log(`  ${yellow('CSC_KEY_PASSWORD')}       ${dim('签名证书密码（与 --cert-password 等效）')}`);

  // 快捷命令
  box('npm 快捷命令');
  console.log(`  ${bold('npm run build:win')}              ${dim('→ node build.mjs --win --build')}`);
  console.log(`  ${bold('npm run build:mac')}              ${dim('→ node build.mjs --mac --build')}`);
  console.log(`  ${bold('npm run build:linux')}            ${dim('→ node build.mjs --linux --build')}`);
  console.log(`  ${bold('npm run build:clean')}            ${dim('→ node scripts/clean.mjs')}`);
  console.log(`  ${bold('npm run upload:oss')}             ${dim('→ node scripts/upload-oss.mjs')}`);
  console.log(`  ${bold('npm run publish:release')}        ${dim('→ node scripts/publish-release.mjs')}`);

  console.log('');
}

// ---------- 入口 ----------

main().catch((err) => {
  console.error(`\n❌ 构建失败: ${err.message}`);
  process.exit(1);
});
