#!/usr/bin/env node
/**
 * 为运行时包生成 OSS 上传清单（不复制文件 — 本地与 CDN 共用同一目录）。
 *
 *   node tools/write-deploy-manifest.js [packDir] [--cdn-base URL] [--manifest-dir DIR] [--zip]
 *
 * 运行时包: build/mstest5/  ← 上传此目录全部内容到 unitycdndir
 * 清单输出: build/deploy/UPLOAD-MANIFEST.txt（不进 OSS）
 */
const fs = require('fs');
const path = require('path');
const { execSync } = require('child_process');
const { dirSize, formatBytes } = require('./package-optimize');
const { listRuntimeFiles, bundleNamesFromCatalog } = require('./runtime-pack');

const argv = process.argv.slice(2);
const flags = new Set(argv.filter((a) => a.startsWith('--')));
const positional = argv.filter((a) => !a.startsWith('--'));

const PROJECT = path.resolve(__dirname, '..');
const packDir = path.resolve(positional[0] || path.join(PROJECT, 'build/mstest5'));
const manifestDir = (() => {
  const i = argv.indexOf('--manifest-dir');
  return path.resolve(i >= 0 ? argv[i + 1] : path.join(PROJECT, 'build/deploy'));
})();
const cdnBase = (() => {
  const i = argv.indexOf('--cdn-base');
  return i >= 0 ? argv[i + 1] : '';
})();
const makeZip = flags.has('--zip');

if (!fs.existsSync(path.join(packDir, 'Build/mstest5.loader.js'))) {
  console.error('错误: 无效运行时包，请先 bash tools/package-for-project.sh');
  console.error('  期望:', packDir);
  process.exit(1);
}

const files = listRuntimeFiles(packDir);
const catalogPath = path.join(packDir, 'StreamingAssets/aa/catalog.json');
const bundleNames = bundleNamesFromCatalog(catalogPath);
const base = (cdnBase || 'https://YOUR_CDN/unitycdndir').replace(/\/$/, '');

fs.mkdirSync(manifestDir, { recursive: true });

const manifestPath = path.join(manifestDir, 'UPLOAD-MANIFEST.txt');
const readmePath = path.join(manifestDir, 'README.txt');

const lines = [
  '# OSS 上传清单（自动生成）',
  `# 生成时间: ${new Date().toISOString()}`,
  `# 运行时包目录: ${packDir}`,
  `# OSS 根路径 (unitycdndir): ${base}`,
  '#',
  '# 上传方式: 将「运行时包目录」内全部内容原样上传到 OSS',
  '# 本地 static/unity 与 OSS 文件完全一致，前端仅 config.js usecdn 切换根 URL',
  '#',
  `#   ossutil cp -r "${packDir}/" oss://BUCKET/PATH/`,
  '',
  '## 运行时包文件（本地 = CDN）',
  ...files.map((f) => `- ${f.rel}`),
  '',
  '## OSS 目标路径',
  ...files.map((f) => `${base}/${f.rel}`),
  '',
  '## 上传后验证',
  `curl -I "${base}/Build/mstest5.loader.js"`,
  `curl -I "${base}/StreamingAssets/aa/catalog.json"`,
  `curl -I "${base}/levels-database.json"`,
  ...bundleNames.map((n) => `curl -I "${base}/StreamingAssets/aa/WebGL/${n}"`),
];
fs.writeFileSync(manifestPath, lines.join('\n'), 'utf8');

const readme = [
  '部署说明',
  '========',
  '',
  `生成: ${new Date().toLocaleString('zh-CN')}`,
  '',
  '运行时包（本地与 OSS 相同）:',
  `  ${packDir}/`,
  '  ├── Build/',
  '  ├── StreamingAssets/',
  '  └── levels-database.json(.br)',
  '',
  '本地:  import-to-unity.sh  → scratch-gui/static/unity/（同上结构）',
  'CDN:   上传运行时包全部内容 → config.js unitycdndir + usecdn:true',
  '',
  `包体积: ${formatBytes(dirSize(packDir))}`,
  `详细路径: ${manifestPath}`,
  '',
  '独立调试页（不进 OSS / static）:',
  `  ${path.join(path.dirname(packDir), 'standalone-player')}/index.html`,
].join('\n');
fs.writeFileSync(readmePath, readme, 'utf8');

let zipPath = '';
if (makeZip) {
  zipPath = path.join(path.dirname(packDir), 'mstest5-runtime.zip');
  if (fs.existsSync(zipPath)) fs.unlinkSync(zipPath);
  const items = ['Build', 'StreamingAssets'];
  if (fs.existsSync(path.join(packDir, 'levels-database.json'))) items.push('levels-database.json');
  if (fs.existsSync(path.join(packDir, 'levels-database.json.br'))) items.push('levels-database.json.br');
  execSync(`cd "${packDir}" && zip -0 -q -r "${zipPath}" ${items.join(' ')}`, { stdio: 'pipe' });
}

console.log('>>> 运行时包:', packDir);
console.log(`>>> 文件数: ${files.length}, 体积: ${formatBytes(dirSize(packDir))}`);
console.log('>>> 上传清单:', manifestPath);
if (zipPath) {
  console.log(`>>> ZIP: ${zipPath} (${formatBytes(fs.statSync(zipPath).size)})`);
}
