// ============================================================
// 上传安装包 + blockmap 文件到阿里云 OSS
//
// 用法（由 build.mjs 调用）：
//   node build/scripts/upload-oss.mjs <platform> <version> <channel> <ossPrefix> <releaseDirName>
//
// 也支持手动调用：
//   node build/scripts/upload-oss.mjs <platform> <version> [channel] [ossPrefix]
//
// 环境变量（使用 Node.js 直传时需要）：
//   OSS_ENDPOINT        — OSS endpoint（如 oss-cn-hangzhou.aliyuncs.com）
//   OSS_BUCKET          — Bucket 名称
//   OSS_ACCESS_KEY_ID     — AccessKey ID
//   OSS_ACCESS_KEY_SECRET — AccessKey Secret
//
// 不传 OSS 环境变量时 → 打印手动上传命令
// ============================================================

import { readFileSync, readdirSync } from 'node:fs';
import { join, dirname } from 'node:path';
import { fileURLToPath } from 'node:url';
import { createHmac } from 'node:crypto';

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

// ---------- 参数 ----------

const platform = process.argv[2];
const version = process.argv[3];
const channel = process.argv[4] || 'stable';
const ossPrefix = process.argv[5] || `releases/${version}`;
const releaseDirName = process.argv[6] || version;

if (!platform || !version) {
  console.error('用法: node build/scripts/upload-oss.mjs <platform> <version> [channel] [ossPrefix] [releaseDirName]');
  process.exit(1);
}

// ---------- 查找安装包 ----------

const releaseDir = join(ROOT, 'release', releaseDirName);

let installerName;
try {
  const all = readdirSync(releaseDir);
  const exts = platform === 'win32' ? ['.exe'] : platform === 'darwin' ? ['.dmg'] : ['.AppImage'];
  installerName = all.find((f) => exts.some((e) => f.endsWith(e)));
  if (!installerName) {
    console.error(`错误: ${releaseDir} — 未找到安装包`);
    process.exit(1);
  }
} catch (err) {
  console.error(`错误: ${releaseDir} — ${err.message}`);
  process.exit(1);
}

const installerPath = join(releaseDir, installerName);

// ---------- 查找 blockmap 文件 ----------

let blockmapName = null;
let blockmapPath = null;
try {
  const all = readdirSync(releaseDir);
  blockmapName = all.find((f) => f.endsWith('.blockmap'));
  if (blockmapName) {
    blockmapPath = join(releaseDir, blockmapName);
  }
} catch {
  // blockmap 不存在不影响主流程
}

// ---------- OSS 配置 ----------

const {
  OSS_ENDPOINT,
  OSS_BUCKET,
  OSS_ACCESS_KEY_ID,
  OSS_ACCESS_KEY_SECRET,
} = process.env;

const installerObjectKey = `${ossPrefix}/${installerName}`;

// ============================================================
// 模式 A：无 OSS 配置 → 打印手动命令
// ============================================================

if (!OSS_ENDPOINT || !OSS_BUCKET || !OSS_ACCESS_KEY_ID) {
  const exampleBucket = OSS_BUCKET || '<bucket>';
  const exampleEndpoint = OSS_ENDPOINT || '<endpoint>';
  const downloadUrl = `https://${exampleBucket}.${exampleEndpoint}/${installerObjectKey}`;

  console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
  console.log('📦 上传安装包 + blockmap（手动）');
  console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
  console.log(`渠道: ${channel}`);
  console.log(`OSS 路径: ${ossPrefix}/`);
  console.log(`文件: ${installerPath}`);
  console.log(`大小: ${(readFileSync(installerPath).length / 1024 / 1024).toFixed(2)} MB\n`);

  if (blockmapPath) {
    console.log(`Blockmap: ${blockmapPath}`);
    console.log(`Blockmap 大小: ${(readFileSync(blockmapPath).length / 1024).toFixed(2)} KB\n`);
  }

  console.log('方式 1 — ossutil CLI（推荐）：');
  console.log(`  ossutil cp "${installerPath}" oss://${exampleBucket}/${installerObjectKey}`);
  if (blockmapPath) {
    const blockmapKey = `${ossPrefix}/${blockmapName}`;
    console.log(`  ossutil cp "${blockmapPath}" oss://${exampleBucket}/${blockmapKey}`);
  }
  console.log('');

  console.log('方式 2 — 阿里云控制台：');
  console.log(`  登录 OSS 控制台 → ${exampleBucket} → 上传 → 目标路径: ${installerObjectKey}`);
  if (blockmapPath) {
    console.log(`  同时上传 ${blockmapName} 到相同目录`);
  }
  console.log('');

  const blockmapUrl = blockmapPath
    ? `https://${exampleBucket}.${exampleEndpoint}/${ossPrefix}/${blockmapName}`
    : '';

  console.log('上传后执行以下命令，用实际 URL 重新生成 info：');
  if (blockmapUrl) {
    console.log(`  node build/scripts/generate-update-info.mjs ${platform} ${version} ${channel} --url "${downloadUrl}" --blockmap-url "${blockmapUrl}"`);
    console.log('');
    console.log('或直接发布到后端 API：');
    console.log(`  node build/scripts/publish-release.mjs ${platform} ${version} ${channel} --url "${downloadUrl}" --blockmap-url "${blockmapUrl}"`);
  } else {
    console.log(`  node build/scripts/generate-update-info.mjs ${platform} ${version} ${channel} --url "${downloadUrl}"`);
    console.log('');
    console.log('或直接发布到后端 API：');
    console.log(`  node build/scripts/publish-release.mjs ${platform} ${version} ${channel} --url "${downloadUrl}"`);
  }
  console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
  process.exit(0);
}

// ============================================================
// 模式 B：Node.js 直传 OSS（安装包 + blockmap）
// ============================================================

const fileBuffer = readFileSync(installerPath);
const contentType = platform === 'win32'
  ? 'application/vnd.microsoft.portable-executable'
  : 'application/octet-stream';

// 上传安装包
const date = new Date().toUTCString();
const stringToSign = [
  'PUT', '', contentType, date, `/${OSS_BUCKET}/${installerObjectKey}`,
].join('\n');
const signature = createHmac('sha1', OSS_ACCESS_KEY_SECRET)
  .update(stringToSign)
  .digest('base64');
const authHeader = `OSS ${OSS_ACCESS_KEY_ID}:${signature}`;
const downloadUrl = `https://${OSS_BUCKET}.${OSS_ENDPOINT}/${installerObjectKey}`;

console.log(`上传中: ${installerName} (${(fileBuffer.length / 1024 / 1024).toFixed(2)} MB)`);
console.log(`渠道: ${channel}`);
console.log(`目标: oss://${OSS_BUCKET}/${installerObjectKey}`);

try {
  const response = await fetch(downloadUrl, {
    method: 'PUT',
    headers: {
      'Content-Type': contentType,
      'Content-Length': String(fileBuffer.length),
      'Date': date,
      'Authorization': authHeader,
    },
    body: fileBuffer,
  });

  if (!response.ok) {
    const body = await response.text();
    console.error(`❌ 安装包上传失败 HTTP ${response.status}: ${body}`);
    process.exit(1);
  }
  console.log('✅ 安装包上传成功');
  console.log(`下载 URL: ${downloadUrl}`);
} catch (err) {
  console.error(`❌ 安装包上传失败: ${err.message}`);
  process.exit(1);
}

// 上传 blockmap 文件
let blockmapUrl = null;
if (blockmapPath) {
  const blockmapBuffer = readFileSync(blockmapPath);
  const blockmapKey = `${ossPrefix}/${blockmapName}`;
  blockmapUrl = `https://${OSS_BUCKET}.${OSS_ENDPOINT}/${blockmapKey}`;

  const bmDate = new Date().toUTCString();
  const bmStringToSign = [
    'PUT', '', 'application/octet-stream', bmDate, `/${OSS_BUCKET}/${blockmapKey}`,
  ].join('\n');
  const bmSignature = createHmac('sha1', OSS_ACCESS_KEY_SECRET)
    .update(bmStringToSign)
    .digest('base64');

  console.log(`\n上传 blockmap: ${blockmapName} (${(blockmapBuffer.length / 1024).toFixed(2)} KB)`);

  try {
    const bmResponse = await fetch(blockmapUrl, {
      method: 'PUT',
      headers: {
        'Content-Type': 'application/octet-stream',
        'Content-Length': String(blockmapBuffer.length),
        'Date': bmDate,
        'Authorization': `OSS ${OSS_ACCESS_KEY_ID}:${bmSignature}`,
      },
      body: blockmapBuffer,
    });

    if (bmResponse.ok) {
      console.log('✅ Blockmap 上传成功');
      console.log(`Blockmap URL: ${blockmapUrl}`);
    } else {
      console.warn(`⚠️  Blockmap 上传失败（不影响主流程），HTTP ${bmResponse.status}`);
      blockmapUrl = null;
    }
  } catch (err) {
    console.warn(`⚠️  Blockmap 上传失败（不影响主流程）: ${err.message}`);
    blockmapUrl = null;
  }
}

// 后续步骤提示
console.log('\n接下来 — 重新生成 update-info.json：');
if (blockmapUrl) {
  console.log(`  node build/scripts/generate-update-info.mjs ${platform} ${version} ${channel} --url "${downloadUrl}" --blockmap-url "${blockmapUrl}"`);
  console.log('\n或直接发布到后端 API：');
  console.log(`  node build/scripts/publish-release.mjs ${platform} ${version} ${channel} --url "${downloadUrl}" --blockmap-url "${blockmapUrl}"`);
} else {
  console.log(`  node build/scripts/generate-update-info.mjs ${platform} ${version} ${channel} --url "${downloadUrl}"`);
  console.log('\n或直接发布到后端 API：');
  console.log(`  node build/scripts/publish-release.mjs ${platform} ${version} ${channel} --url "${downloadUrl}"`);
}
