#!/usr/bin/env node

import { execSync, spawn } from 'child_process';
import { platform } from 'os';
import { existsSync, readFileSync, readdirSync, rmSync, writeFileSync } from 'fs';
import { join } from 'path';
import {
  APPLE_CERTIFICATE,
  APPLE_CERTIFICATE_PASSWORD,
  APPLE_ID,
  APPLE_PASSWORD,
  APPLE_SIGNING_IDENTITY,
  APPLE_TEAM_ID,
  TAURI_SIGNING_PRIVATE_KEY,
  TAURI_SIGNING_PRIVATE_KEY_PASSWORD,
} from './utils/constant.ts';

// ==================== 解析命令行参数 ====================
// 从命令行参数中获取 --features 的值
const args: string[] = process.argv.slice(2);
const featuresIndex: number = args.findIndex((arg: string) => arg === '--features');
const buildFeature: string = featuresIndex !== -1 && args[featuresIndex + 1] ? (args[featuresIndex + 1] as string) : 'production';

// 根据 feature 设置对应的环境模式
const modeMap: Record<string, string> = {
  production: 'production',
  development: 'development',
  prod_150_8080: 'prod_150_8080',
};
const buildMode: string = (buildFeature in modeMap ? modeMap[buildFeature as keyof typeof modeMap] : modeMap.production) || 'production';

console.log('\x1b[36m%s\x1b[0m', `构建配置: --features ${buildFeature}, --mode ${buildMode}`);

// ==================== updater签名环境变量配置 ====================
// 私匙
process.env.TAURI_SIGNING_PRIVATE_KEY = TAURI_SIGNING_PRIVATE_KEY;
// 私匙对应的密码，没有就不配置
process.env.TAURI_SIGNING_PRIVATE_KEY_PASSWORD = TAURI_SIGNING_PRIVATE_KEY_PASSWORD;

// Mac 公证
if (platform() === 'darwin') {
  /** 签名证书在钥匙串中的名称（签名标识） */
  process.env.APPLE_SIGNING_IDENTITY = APPLE_SIGNING_IDENTITY;
  /** 从钥匙串导出的 .p12 证书的 base64 字符串（适用于 CI 或没有本地证书时） */
  process.env.APPLE_CERTIFICATE = APPLE_CERTIFICATE;
  /** .p12 证书的密码。 */
  process.env.APPLE_CERTIFICATE_PASSWORD = APPLE_CERTIFICATE_PASSWORD;
  /** 你的 Apple 账号邮箱（用于公证） */
  process.env.APPLE_ID = APPLE_ID;
  /** Apple 账号的 App 专用密码（用于公证） */
  process.env.APPLE_PASSWORD = APPLE_PASSWORD;
  /** 你的 Apple 开发者团队 ID（用于公证） */
  process.env.APPLE_TEAM_ID = APPLE_TEAM_ID;
}

// 运行版本更新脚本，同步 tauri.conf.json 和 package.json 的版本号
console.log('\x1b[36m%s\x1b[0m', '正在同步版本号...');
try {
  const updateVersionScriptPath = join('.', 'vite', 'scripts', 'update-version.ts');
  execSync(`node "${updateVersionScriptPath}"`, { stdio: 'inherit' });
  console.log('\x1b[32m%s\x1b[0m', '版本号同步完成');
} catch (error: any) {
  console.error('\x1b[31m%s\x1b[0m', '版本号同步失败:', error.message);
  process.exit(1);
}

// 读取更新后的 package.json 获取版本号
interface PackageJson {
  version: string;
  [key: string]: any;
}

const packageJsonPath = join('package.json');
let packageJson: PackageJson = {} as PackageJson;
try {
  packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf8'));
} catch (error: any) {
  console.error('\x1b[31m%s\x1b[0m', '读取 package.json 失败:', error.message);
  process.exit(1);
}

// 获取当前版本号
const newVersion: string = packageJson.version;

// 在构建前删除 src-tauri/target/release/bundle 目录内容
const bundleDir = join('src-tauri', 'target', 'release', 'bundle');
if (existsSync(bundleDir)) {
  console.log('\x1b[33m%s\x1b[0m', `正在删除 ${bundleDir} 目录内容...`);
  rmSync(bundleDir, { recursive: true, force: true });
}

// 先执行 Vite 默认配置构建
console.log('\x1b[36m%s\x1b[0m', '正在构建 index.html入口...');
const viteBuild = spawn('vite', ['build', '--mode', buildMode], {
  stdio: 'inherit',
  shell: true,
  env: { ...process.env },
});

viteBuild.on('close', (code) => {
  if (code !== 0) {
    console.error('\x1b[31m%s\x1b[0m', `Vite 打包 index.html失败，退出码: ${code}`);
    process.exit(code);
  }

  console.log('\x1b[36m%s\x1b[0m', '正在构建 其他.html入口...');
  const viteSimplifiedBuild = spawn('vite', ['build', '--config', 'vite.simplified.config.ts', '--mode', buildMode], {
    stdio: 'inherit',
    shell: true,
    env: { ...process.env },
  });

  viteSimplifiedBuild.on('close', (simplifiedCode) => {
    if (simplifiedCode !== 0) {
      console.error('\x1b[31m%s\x1b[0m', `Vite 打包 其他.html入口构建失败，退出码: ${simplifiedCode}`);
      process.exit(simplifiedCode);
    }

    console.log('\x1b[36m%s\x1b[0m', 'Vite 构建完成，开始执行 Tauri 构建...');
    const tauriBuild = spawn('tauri', ['build', '--features', buildFeature], {
      stdio: 'inherit',
      shell: true,
      env: process.env, // 传递所有环境变量
    });

    tauriBuild.on('close', (tauriCode) => {
      if (tauriCode === 0) {
        // 写入 latest.json 到 bundle 目录
        const latestJsonPath = join(bundleDir, 'latest.json');
        // 为不同平台生成相应的 latest.json
        if (platform() === 'win32') {
          const latestJson = getLatestJson('windows', newVersion, 'nsis', 'exe');
          writeFileSync(latestJsonPath, JSON.stringify(latestJson, null, 2));
          console.log('\x1b[32m%s\x1b[0m', `已生成 latest.json 文件: ${latestJsonPath}`);
        } else if (platform() === 'darwin') {
          const latestJson = getLatestJson('macos', newVersion, 'macos', 'app.tar.gz');
          writeFileSync(latestJsonPath, JSON.stringify(latestJson, null, 2));
          console.log('\x1b[32m%s\x1b[0m', `已生成 latest.json 文件: ${latestJsonPath}`);
        } else if (platform() === 'linux') {
          // 为 AppImage 生成 latest.json
          const appImageLatest = getLatestJson('linux', newVersion, 'appimage', 'AppImage');
          writeFileSync(join(bundleDir, 'appimage', 'latest.json'), JSON.stringify(appImageLatest, null, 2));
          console.log('\x1b[32m%s\x1b[0m', `已生成 appimage-latest.json 文件`);

          // 为 deb 生成 latest.json
          const debLatest = getLatestJson('linux', newVersion, 'deb', 'deb');
          writeFileSync(join(bundleDir, 'deb', 'latest.json'), JSON.stringify(debLatest, null, 2));
          console.log('\x1b[32m%s\x1b[0m', `已生成 deb-latest.json 文件`);

          // 为 rpm 生成 latest.json
          const rpmLatest = getLatestJson('linux', newVersion, 'rpm', 'rpm');
          writeFileSync(join(bundleDir, 'rpm', 'latest.json'), JSON.stringify(rpmLatest, null, 2));
          console.log('\x1b[32m%s\x1b[0m', `已生成 rpm-latest.json 文件`);
        }

        // Tauri 构建成功后执行自动部署
        console.log('\x1b[36m%s\x1b[0m', '开始执行自动部署...');
        try {
          const autoDeployScriptPath = join('.', 'vite', 'scripts', 'auto-deply.ts');
          execSync(`npx tsx "${autoDeployScriptPath}"`, { stdio: 'inherit' });
          console.log('\x1b[32m%s\x1b[0m', '自动部署执行完成');
        } catch (error: any) {
          console.error('\x1b[31m%s\x1b[0m', '自动部署执行失败:', error.message);
          // 注意：这里不退出进程，因为构建本身是成功的
        }
      } else {
        console.error('\x1b[31m%s\x1b[0m', `Tauri 构建失败，退出码: ${tauriCode}`);
        process.exit(tauriCode);
      }
    });
  });
});

/**
 * 得到最新版本信息
 * @param ostype - 平台类型，如 'windows'、'macos'、'linux'
 * @param version - 新版本号
 * @param catalog - 包的目录名
 * @param extension - 包的扩展名
 */
interface LatestJson {
  version: string;
  pub_date: string;
  url: string;
  signature: string;
  notes: string;
  downloadLink?: string;
}

/**
 * 获取最新版本信息
 * @param ostype - 平台类型，如 'windows'、'macos'、'linux'
 * @param version - 新版本号
 * @param catalog - 包的目录名
 * @param extension - 包的扩展名
 */
function getLatestJson(ostype: string, version: string, catalog: string, extension: string): LatestJson {
  const pubDate = new Date().toISOString();
  const latestJson: LatestJson = {
    version,
    pub_date: pubDate,
    url: '',
    signature: '',
    notes: '1. 修复BUG \n 2. 优化部分功能',
  };
  const baseUrl = `https://file.qyzhjy.com/app/zpkt_desktop_app/${ostype}`;
  try {
    if (ostype === 'windows') {
      const nsisDir = join(bundleDir, catalog);
      const files = readdirSync(nsisDir);
      const exeFile = files.find((file) => file.endsWith('exe'));
      latestJson.downloadLink = `${baseUrl}/${catalog}/${exeFile}`;
    } else if (ostype === 'macos') {
      const dmgDir = join(bundleDir, 'dmg');
      const files = readdirSync(dmgDir);
      const dmgFile = files.find((file) => file.endsWith('dmg'));
      latestJson.downloadLink = `${baseUrl}/dmg/${dmgFile}`;
    } else if (ostype === 'linux') {
      const appImageDir = join(bundleDir, catalog);
      const files = readdirSync(appImageDir);
      const appImageFile = files.find((file) => file.endsWith(extension));
      latestJson.downloadLink = `${baseUrl}/${catalog}/${appImageFile}`;
    }

    // 查找 nsis 目录下的 exe 文件
    const nsisDir = join(bundleDir, catalog);
    if (existsSync(nsisDir)) {
      const files = readdirSync(nsisDir);
      const exeFile = files.find((file) => file.endsWith(extension));
      const sigFile = files.find((file) => file.endsWith(`${extension}.sig`));
      if (exeFile) {
        // 设置 Windows 平台的 URL
        latestJson.url = `${baseUrl}/${catalog}/${exeFile}`;
        // 如果存在对应的 .sig 文件，读取签名内容
        if (sigFile) {
          const sigFilePath = join(nsisDir, sigFile);
          latestJson.signature = readFileSync(sigFilePath, 'utf8').trim();
        }
      }
    }
    return latestJson;
  } catch (error: any) {
    console.warn('\x1b[33m%s\x1b[0m', '警告: 无法读取 Windows 安装包信息:', error.message);
    return latestJson;
  }
}
