#!/usr/bin/env node
// ════════════════════════════════════════════════════════════════
// 光湖搬家 · convert-workflows
// Sovereign: TCS-0002∞ · 国作登字-2026-A-00037559
// 守护: 铸渊 · ICE-GL-ZY001
//
// 把 .github/workflows/*.yml 转成 Gitea Actions 兼容版本到 .gitea/workflows/.
// Gitea Actions 与 GitHub Actions 兼容 ≥95%, 这里处理已知不兼容点:
//   - secrets.GITHUB_TOKEN  →  secrets.GITEA_TOKEN
//   - actions/checkout@v4   保持 (Gitea 1.21+ 已支持)
//   - actions/upload-artifact / download-artifact  保持
//   - github.event.* 保持 (Gitea 自身的 webhook event 同名)
//   - 移除/标记 GitHub-only feature: id-token oidc, codeql-action
//
// 用法:
//   node scripts/migration/convert-workflows.js \
//     --from .github/workflows \
//     --to .gitea/workflows \
//     --report convert-report.json \
//     [--keep-original]   # 不删原始文件
// ════════════════════════════════════════════════════════════════

'use strict';

const fs = require('fs');
const path = require('path');

function parseArgs(argv) {
  const args = {
    from: '.github/workflows',
    to: '.gitea/workflows',
    report: null,
    keepOriginal: true,
  };
  for (let i = 2; i < argv.length; i++) {
    const a = argv[i];
    if (a === '--from') args.from = argv[++i];
    else if (a === '--to') args.to = argv[++i];
    else if (a === '--report') args.report = argv[++i];
    else if (a === '--keep-original') args.keepOriginal = true;
    else if (a === '--no-keep-original') args.keepOriginal = false;
    else if (a === '-h' || a === '--help') {
      console.log(fs.readFileSync(__filename, 'utf8').split('\n').slice(0, 25).join('\n'));
      process.exit(0);
    }
  }
  return args;
}

const args = parseArgs(process.argv);

const FROM = path.resolve(args.from);
const TO = path.resolve(args.to);

if (!fs.existsSync(FROM)) {
  console.error(`❌ 源目录不存在: ${FROM}`);
  process.exit(1);
}
fs.mkdirSync(TO, { recursive: true });

// ─── 转换规则 ──────────────────────────────────────────────
// 每条规则: { name, match (regex|fn), replace (string|fn), severity }
// severity:
//   safe    - 自动改写, 改完依然 100% 行为一致
//   review  - 自动改写, 但建议人工 review
//   skip    - 不能转, 整文件标记 unconvertible
const RULES = [
  {
    name: 'GITHUB_TOKEN → GITEA_TOKEN',
    match: /\bsecrets\.GITHUB_TOKEN\b/g,
    replace: 'secrets.GITEA_TOKEN',
    severity: 'safe',
  },
  {
    name: 'github.token → gitea.token',
    match: /\$\{\{\s*github\.token\s*\}\}/g,
    replace: '${{ secrets.GITEA_TOKEN }}',
    severity: 'safe',
  },
  {
    name: 'env.GITHUB_TOKEN → env.GITEA_TOKEN (in env: blocks)',
    match: /(\benv:\s*\n(?:\s+\w+:.*\n)*?\s+)GITHUB_TOKEN(\s*:)/g,
    replace: '$1GITEA_TOKEN$2',
    severity: 'safe',
  },
  {
    name: 'OIDC id-token (GitHub-only) ',
    match: /\bid-token:\s*write\b/g,
    replace: '# id-token: write  # [removed: OIDC GitHub-only]',
    severity: 'review',
  },
  {
    name: 'github/codeql-action (GitHub-only)',
    match: /uses:\s*github\/codeql-action\/[^\s]+/g,
    replace: (m) => `# ${m}  # [unconvertible: codeql is GitHub-only]`,
    severity: 'skip',
  },
  {
    name: 'github-script v6 fetch.toJson (兼容差异)',
    match: /uses:\s*actions\/github-script@v[0-9]+/g,
    replace: (m) => m, // 保持, 但提示 review
    severity: 'review',
    note: 'github-script 在 Gitea 上需要 octokit 兼容版本, 部分 rest API 路径可能不同',
  },
  {
    name: 'pull_request_target (Gitea 1.21 才支持)',
    match: /^\s*pull_request_target\s*:/m,
    replace: (m) => m,
    severity: 'review',
    note: '需要 Gitea ≥ 1.21.0',
  },
  {
    name: '自托管 runner 标签',
    match: /runs-on:\s*ubuntu-latest/g,
    replace: 'runs-on: ubuntu-22.04',
    severity: 'safe',
    note: '统一使用 ubuntu-22.04 标签, 与 act_runner 默认 label 对齐',
  },
];

// ─── 主流程 ────────────────────────────────────────────────
const report = {
  _sovereign: 'TCS-0002∞',
  _copyright: '国作登字-2026-A-00037559',
  generated_at: new Date().toISOString(),
  source_dir: FROM,
  target_dir: TO,
  files: [],
  unconvertible: [],
  summary: { total: 0, converted: 0, review_needed: 0, skipped: 0 },
};

const files = fs.readdirSync(FROM).filter((f) => f.endsWith('.yml') || f.endsWith('.yaml'));
report.summary.total = files.length;

for (const f of files) {
  const src = fs.readFileSync(path.join(FROM, f), 'utf8');
  let dst = src;
  const fileEntry = { file: f, applied: [], severity: 'safe', notes: [] };

  for (const rule of RULES) {
    if (rule.match instanceof RegExp) {
      // 测试是否匹配
      const before = dst;
      if (typeof rule.replace === 'function') {
        dst = dst.replace(rule.match, rule.replace);
      } else {
        dst = dst.replace(rule.match, rule.replace);
      }
      if (before !== dst) {
        fileEntry.applied.push(rule.name);
        if (rule.severity === 'review' && fileEntry.severity !== 'skip') fileEntry.severity = 'review';
        if (rule.severity === 'skip') fileEntry.severity = 'skip';
        if (rule.note) fileEntry.notes.push(rule.note);
      }
    }
  }

  // 头部加一行铸渊签名 (基于 src 而非 dst 判断, 避免重复运行重复加)
  if (!src.startsWith('# Generated by convert-workflows')) {
    dst = `# Generated by scripts/migration/convert-workflows.js @ ${new Date().toISOString()}\n# Sovereign: TCS-0002∞ · 国作登字-2026-A-00037559\n${dst}`;
  }

  if (fileEntry.severity === 'skip') {
    report.unconvertible.push({ ...fileEntry });
    report.summary.skipped += 1;
  } else {
    fs.writeFileSync(path.join(TO, f), dst);
    report.summary.converted += 1;
    if (fileEntry.severity === 'review') report.summary.review_needed += 1;
  }
  report.files.push(fileEntry);
}

if (args.report) {
  fs.writeFileSync(args.report, JSON.stringify(report, null, 2));
}

console.log('═══════════════════════════════════════════════════════');
console.log('  workflow 转换完成');
console.log(`  total       : ${report.summary.total}`);
console.log(`  converted   : ${report.summary.converted}`);
console.log(`  review-need : ${report.summary.review_needed}`);
console.log(`  skipped     : ${report.summary.skipped}`);
console.log('═══════════════════════════════════════════════════════');
if (report.summary.skipped > 0) {
  console.log('⚠️  以下文件无法自动转换, 需人工介入:');
  for (const u of report.unconvertible) {
    console.log(`  - ${u.file}: ${u.applied.join(', ')}`);
  }
}
if (args.report) {
  console.log(`详细报告: ${args.report}`);
}
