const core = require('@actions/core');
const exec = require('@actions/exec');
const fs = require('fs');
const path = require('path');
const { formatReportLines } = require('./display');

const TOOL_URL = 'https://gitcode.com/openlibing/openlibing-api-parser.git';

function deriveContext() {
  const repository = process.env.ATOMGIT_REPOSITORY || process.env.GITHUB_REPOSITORY || '';
  const repoUrl = process.env.ATOMGIT_REPOSITORYURL
    || process.env.ATOMGIT_REPOSITORY_URL
    || (repository ? `https://gitcode.com/${repository}.git` : '');
  const commitId = process.env.ATOMGIT_SHA || process.env.ATOMGIT_WORKFLOW_SHA || process.env.GITHUB_SHA || '';
  const mergeId = process.env.MERGE_ID || '';
  return { repoUrl, mergeId, commitId };
}

async function run() {
  const workspace = process.env.ATOMGIT_WORKSPACE || process.env.GITHUB_WORKSPACE || process.cwd();
  const uploadUrl = core.getInput('upload_url') || 'https://apig.openlibing.com:443/openlibing-design-api-management/interface/pr-control/report';
  const toolRef = core.getInput('tool_ref') || 'master';
  const skipInstall = (core.getInput('skip_install') || 'true').toLowerCase() === 'true';
  const exclude = core.getInput('exclude') || '.api-parser-tool';
  const debug = (core.getInput('debug') || 'false').toLowerCase() === 'true';

  const { repoUrl, mergeId, commitId } = deriveContext();

  const toolDir = path.join(workspace, '.api-parser-tool');
  const scanSh = path.join(toolDir, 'scripts', 'openlibing_scan.sh');
  const cliPy = path.join(toolDir, 'cli.py');
  const apiAnalysis = path.join(toolDir, 'tools', 'api_analysis', 'linux-x86_64-ubuntu22-llvm15', 'api_analysis');
  const reqPath = path.join(toolDir, 'requirements.txt');
  const resultFile = path.join(toolDir, 'results.json');

  try {
    core.info('API-Miner Start ...');
    core.info(`REPO_URL=${repoUrl}`);
    core.info(`PR_ID=${mergeId}`);
    core.info(`COMMIT=${commitId}`);

    if (fs.existsSync(toolDir)) {
      fs.rmSync(toolDir, { recursive: true, force: true });
    }

    core.info(`Cloning api-parser tool: ref=${toolRef}`);
    await exec.exec('git', ['clone', '-b', toolRef, TOOL_URL, toolDir]);

    for (const f of [scanSh, cliPy, apiAnalysis]) {
      try {
        fs.chmodSync(f, 0o755);
      } catch (e) {
        core.warning(`chmod failed for ${f}: ${e.message}`);
      }
    }

    core.info('Installing python dependencies ...');
    await exec.exec('pip3', ['install', '--break-system-packages', '-r', reqPath, '-i', 'https://pypi.tuna.tsinghua.edu.cn/simple']);

    const scanArgs = [
      scanSh,
      '--source', workspace,
      '--exclude', exclude,
      '--output', resultFile,
    ];
    if (skipInstall) {
      scanArgs.push('--skip-install');
    }

    core.info('Running api-scan ...');
    const scanExit = await exec.exec('bash', scanArgs, { ignoreReturnCode: true, env: { ...process.env, PYTHON_BIN: 'python3' } });
    if (scanExit !== 0) {
      core.setFailed(`API-Miner scan failed with exit code ${scanExit}`);
      return;
    }
    core.info('API-Miner scan succeeded, uploading results via OIDC ...');

    // 上传改由 Node 侧 callApig 完成(OIDC 免密换证 + V11 签名 + X-Security-Token),
    // Python 工具只负责扫描并写 results.json。上传失败不阻断 PR 门禁。
    try {
      const body = fs.readFileSync(resultFile, 'utf8');
      const { callApig, configure } = require('@openlibing/huaweicloud-oidc-client');
      if (debug) configure({ debug: true });
      const res = await callApig(
        'POST',
        uploadUrl,
        { 'repo_url': repoUrl, 'merge_id': mergeId, 'commit_id': commitId },
        body
      );
      if (res.status >= 200 && res.status < 300) {
        core.info(`✅ 上报成功! 状态码: ${res.status}`);
      } else {
        core.warning(`上传返回异常状态码: ${res.status}(不阻断 PR 门禁)`);
      }
      core.info('📋 响应内容:');
      for (const line of formatReportLines(res.data)) {
        core.info(line);
      }
      // 有不兼容变更则阻断 PR 门禁(红叉),而非仅暴露问题仍绿色通过
      const envelope = res.data && typeof res.data === 'object' ? res.data : {};
      const inner = envelope.data && typeof envelope.data === 'object' ? envelope.data : {};
      const ccb = inner.compatibilityCountBody || {};
      const incompatible = Number(ccb.incompatible || 0);
      const scanResult = String(inner.scanResult || '');
      if (incompatible > 0 || scanResult.includes('不通过')) {
        core.setFailed(`检测到 ${incompatible} 个不兼容变更,PR 门禁未通过`);
      }
    } catch (e) {
      core.warning(`OIDC 上传失败(不阻断): ${e && e.message ? e.message : e}`);
    }
  } finally {
    try {
      if (fs.existsSync(toolDir)) {
        fs.rmSync(toolDir, { recursive: true, force: true });
      }
    } catch (e) {
      core.warning(`cleanup failed: ${e.message}`);
    }
  }
}

run().catch(err => core.setFailed(`Unexpected error: ${err && err.message ? err.message : err}`));