/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

import { pathToFileURL } from 'node:url';

export function parseProductReleaseVersion(version) {
  if (typeof version !== 'string') throw new Error('Expected a valid product release version');
  const match =
    /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?$/u.exec(
      version,
    );
  if (!match) throw new Error(`Expected a valid product release version; found ${version}`);
  const prerelease = match[4]?.split('.') ?? [];
  if (
    prerelease.some(
      (identifier) => /^\d+$/u.test(identifier) && identifier.length > 1 && identifier[0] === '0',
    )
  ) {
    throw new Error(`Expected a valid product release version; found ${version}`);
  }
  return {
    version,
    core: [BigInt(match[1]), BigInt(match[2]), BigInt(match[3])],
    prerelease,
  };
}

export function assertProductNightlyVersion(version, productVersion) {
  const product = parseProductReleaseVersion(productVersion);
  if (product.prerelease.length > 0) {
    throw new Error('Product Nightly requires a stable checked-in product version');
  }
  const nightly = parseProductNightlyVersion(version);
  if (nightly.core.some((identifier, index) => identifier !== product.core[index])) {
    throw new Error(`Product Nightly version ${version} must be a dev build of ${productVersion}`);
  }
  return version;
}

export function parseProductNightlyVersion(version) {
  const nightly = parseProductReleaseVersion(version);
  if (
    nightly.prerelease.length !== 3 ||
    nightly.prerelease[0] !== 'dev' ||
    !/^[1-9]\d*$/u.test(nightly.prerelease[1]) ||
    !/^\d{8}$/u.test(nightly.prerelease[2])
  ) {
    throw new Error(`Expected a valid Product Nightly version; found ${version}`);
  }
  return nightly;
}

export function productNightlyRunNumber(version) {
  return BigInt(parseProductNightlyVersion(version).prerelease[1]);
}

export function assertProductNightlyAdvances(candidateVersion, currentVersion, productVersion) {
  assertProductNightlyVersion(candidateVersion, productVersion);
  const candidateRun = productNightlyRunNumber(candidateVersion);
  if (currentVersion === undefined || currentVersion === null || currentVersion === '') {
    return candidateVersion;
  }
  const currentRun = productNightlyRunNumber(currentVersion);
  if (candidateRun <= currentRun) {
    throw new Error(
      `Product Nightly ${candidateVersion} does not advance current run ${currentVersion}`,
    );
  }
  return candidateVersion;
}

export function compareProductReleaseVersions(left, right) {
  const a = parseProductReleaseVersion(left);
  const b = parseProductReleaseVersion(right);
  for (let index = 0; index < a.core.length; index += 1) {
    if (a.core[index] < b.core[index]) return -1;
    if (a.core[index] > b.core[index]) return 1;
  }
  if (a.prerelease.length === 0) return b.prerelease.length === 0 ? 0 : 1;
  if (b.prerelease.length === 0) return -1;
  for (let index = 0; index < Math.max(a.prerelease.length, b.prerelease.length); index += 1) {
    const leftIdentifier = a.prerelease[index];
    const rightIdentifier = b.prerelease[index];
    if (leftIdentifier === undefined) return -1;
    if (rightIdentifier === undefined) return 1;
    if (leftIdentifier === rightIdentifier) continue;
    const leftNumeric = /^\d+$/u.test(leftIdentifier);
    const rightNumeric = /^\d+$/u.test(rightIdentifier);
    if (leftNumeric && rightNumeric) {
      return BigInt(leftIdentifier) < BigInt(rightIdentifier) ? -1 : 1;
    }
    if (leftNumeric) return -1;
    if (rightNumeric) return 1;
    return leftIdentifier < rightIdentifier ? -1 : 1;
  }
  return 0;
}

if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
  const [version] = process.argv.slice(2);
  if (!version || process.argv.length !== 3) {
    throw new Error('usage: release-version.mjs <version>');
  }
  parseProductReleaseVersion(version);
}
