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

const rootDir = path.resolve(__dirname, '..');
const packageJsonPath = path.join(rootDir, 'package.json');

function parseArgs(argv) {
  const args = {};

  for (let index = 0; index < argv.length; index += 1) {
    const token = argv[index];

    if (!token.startsWith('--')) {
      continue;
    }

    const key = token.slice(2);
    const nextToken = argv[index + 1];

    if (!nextToken || nextToken.startsWith('--')) {
      args[key] = true;
      continue;
    }

    args[key] = nextToken;
    index += 1;
  }

  return args;
}

function normalizeVersion(rawValue) {
  if (typeof rawValue !== 'string') {
    return null;
  }

  const trimmedValue = rawValue.trim();

  if (!trimmedValue) {
    return null;
  }

  return trimmedValue.replace(/^v/i, '').split('+')[0] || null;
}

function parseVersion(rawValue) {
  const normalized = normalizeVersion(rawValue);

  if (!normalized) {
    return null;
  }

  const match = normalized.match(/^(\d+)\.(\d+)\.(\d+)(?:-[0-9A-Za-z.-]+)?$/);

  if (!match) {
    return null;
  }

  return {
    major: Number.parseInt(match[1], 10),
    minor: Number.parseInt(match[2], 10),
    patch: Number.parseInt(match[3], 10)
  };
}

function resolveBaseVersion() {
  const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
  const parsedVersion = parseVersion(packageJson.version);

  if (!parsedVersion) {
    throw new Error(`package.json version must be a full semver string. Received: ${packageJson.version}`);
  }

  return parsedVersion;
}

function resolveReleaseVersion(args) {
  const explicitVersion = normalizeVersion(args.version || process.env.RELEASE_VERSION);

  if (explicitVersion) {
    return explicitVersion;
  }

  const baseVersion = resolveBaseVersion();
  const rawRunNumber = args['run-number'] || process.env.GITHUB_RUN_NUMBER || process.env.GITEA_RUN_NUMBER;
  const parsedRunNumber = Number.parseInt(String(rawRunNumber || '').trim(), 10);

  if (Number.isFinite(parsedRunNumber) && parsedRunNumber > 0) {
    return `${baseVersion.major}.${baseVersion.minor}.${baseVersion.patch + parsedRunNumber}`;
  }

  return `${baseVersion.major}.${baseVersion.minor}.${baseVersion.patch}`;
}

function appendOutputLine(outputPath, key, value) {
  fs.appendFileSync(outputPath, `${key}=${value}\n`, 'utf8');
}

function main() {
  const args = parseArgs(process.argv.slice(2));
  const version = resolveReleaseVersion(args);
  const tag = typeof args.tag === 'string' && args.tag.trim().length > 0
    ? args.tag.trim()
    : `v${version}`;
  const result = {
    release_name: `MetoYou ${version}`,
    release_tag: tag,
    release_version: version
  };

  if (args['write-output']) {
    if (!process.env.GITHUB_OUTPUT) {
      throw new Error('GITHUB_OUTPUT is not set.');
    }

    appendOutputLine(process.env.GITHUB_OUTPUT, 'release_version', result.release_version);
    appendOutputLine(process.env.GITHUB_OUTPUT, 'release_tag', result.release_tag);
    appendOutputLine(process.env.GITHUB_OUTPUT, 'release_name', result.release_name);
  }

  if (args.json) {
    console.log(JSON.stringify(result, null, 2));
    return;
  }

  console.log(result.release_version);
}

try {
  main();
} catch (error) {
  const message = error instanceof Error ? error.message : String(error);

  console.error(`[release-version] ${message}`);
  process.exitCode = 1;
}
