// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
// This module is browser compatible.
import { INVALID, MAX, MIN } from "./constants.ts";
import { satisfies } from "./satisfies.ts";
import type { Comparator, Range, SemVer } from "./types.ts";
import { lessThan } from "./less_than.ts";
import { greaterThan } from "./greater_than.ts";
import { increment } from "./increment.ts";
import { isWildcardComparator } from "./_shared.ts";

function comparatorMin(comparator: Comparator): SemVer {
  const semver = comparator;
  if (isWildcardComparator(semver)) return MIN;
  switch (comparator.operator) {
    case ">":
      return semver.prerelease && semver.prerelease.length > 0
        ? increment(semver, "pre")
        : increment(semver, "patch");
    case "!=":
    case "<=":
    case "<":
      // The min(<0.0.0) is MAX
      return greaterThan(semver, MIN) ? MIN : MAX;
    case ">=":
    case undefined:
    case "=":
      return {
        major: semver.major,
        minor: semver.minor,
        patch: semver.patch,
        prerelease: semver.prerelease,
        build: semver.build,
      };
  }
}

/**
 * The minimum valid SemVer for a given range or INVALID
 *
 * @example Usage
 * ```ts
 * import { parseRange } from "@std/semver/parse-range";
 * import { rangeMin } from "@std/semver/range-min";
 * import { equals } from "@std/semver/equals";
 * import { assert } from "@std/assert/assert";
 *
 * assert(equals(rangeMin(parseRange(">=1.0.0 <2.0.0")), { major: 1, minor: 0, patch: 0 }));
 * ```
 *
 * @param range The range to calculate the min for
 * @returns A valid SemVer or INVALID
 *
 * @deprecated This will be removed in 1.0.0. Use {@linkcode greaterThanRange} or
 * {@linkcode lessThanRange} for comparing ranges and SemVers. The minimum
 * version of a range is often not well defined, and therefore this API
 * shouldn't be used. See
 * {@link https://github.com/denoland/deno_std/issues/4365} for details.
 */
export function rangeMin(range: Range): SemVer {
  let min;
  for (const comparators of range) {
    for (const comparator of comparators) {
      const candidate = comparatorMin(comparator);
      if (!satisfies(candidate, range)) continue;
      min = (min && lessThan(min, candidate)) ? min : candidate;
    }
  }
  return min ?? INVALID;
}

// denoCacheMetadata={"headers":{"server":"cloudflare","x-content-type-options":"nosniff","set-cookie":"__cf_bm=Pfl5AVAjQLad_llt85DYej.qM8GESxO080VT..h1onY-1785241875.1653342-1.0.1.1-9OJuIR.Y5_IKwTX2ohl3zh0xlityOsyVlp4XU.tI7KZ6gLoNCd7EV1N5Dh2Q4hk8DhZKKhfrPwSi0PYd2rrpTjGmvoRfiYRTLLm1Xz5QGFc3fp.NbjPIKmnyipsombbo; HttpOnly; SameSite=None; Secure; Path=/; Domain=jsr.io; Expires=Tue, 28 Jul 2026 13:01:15 GMT","vary":"Origin","content-type":"text/typescript","cf-ray":"a223e657ca7a7db6-LAX","access-control-allow-origin":"*","etag":"\"785a52cd229adcb87a7ad594f85b3a2e\"","cf-cache-status":"HIT","cross-origin-resource-policy":"cross-origin","content-security-policy":"default-src 'none'; script-src 'none'; style-src 'none'; img-src 'none'; font-src 'none'; connect-src 'none'; frame-src 'none'; object-src 'none'; frame-ancestors 'none'; sandbox; form-action 'none';","cache-control":"public, max-age=31536000, immutable","content-length":"2310","alt-svc":"h3=\":443\"; ma=86400","nel":"{\"report_to\":\"cf-nel\",\"success_fraction\":0.0,\"max_age\":604800}","accept-ranges":"bytes","x-jsr-backend":"modules","report-to":"{\"group\":\"cf-nel\",\"max_age\":604800,\"endpoints\":[{\"url\":\"https://a.nel.cloudflare.com/report/v4?s=02vThO%2BqjsSsFo3yo%2B4%2BiIPtIBNu8Ri3nM5vBzwTyw5U1QbiGsTOmOYE4W7DU1RBmOBIRwLwvf6Y5DNgxLMRwkPQdnOAuJK00GvX5%2FJWzGCSURo2rVu6ggM%3D\"}]}","date":"Tue, 28 Jul 2026 12:31:15 GMT","age":"3116065","access-control-expose-headers":"*","x-robots-tag":"noindex"},"url":"https://jsr.io/@std/semver/0.224.3/range_min.ts","time":1785241875}