# Copyright 2026 Pex project contributors.
# Licensed under the Apache License, Version 2.0 (see LICENSE).

from __future__ import absolute_import

import sys
from collections import defaultdict

import pytest

from pex import targets
from pex.interpreter import PythonInterpreter
from pex.pep_440 import Version
from pex.pep_503 import ProjectName
from pex.resolve.lockfile import json_codec
from pex.typing import TYPE_CHECKING
from testing import PY27, PY311, ensure_python_interpreter
from testing.cli import run_pex3
from testing.pytest_utils.tmp import Tempdir

if TYPE_CHECKING:
    from typing import DefaultDict, List


def assert_split_cowsay_lock(lock_file):
    # type: (str) -> str

    lock = json_codec.load(lock_file)
    assert len(lock.locked_resolves) == 2
    assert len(lock.locked_resolves[0].locked_requirements) == 1
    assert len(lock.locked_resolves[1].locked_requirements) == 1

    versions_by_project_name = defaultdict(list)  # type: DefaultDict[ProjectName, List[Version]]
    for locked_resolve in lock.locked_resolves:
        for locked_requirement in locked_resolve.locked_requirements:
            versions_by_project_name[locked_requirement.pin.project_name].append(
                locked_requirement.pin.version
            )
    assert len(versions_by_project_name) == 1, "Should only have locked the cowsay project."
    locked_versions = versions_by_project_name.pop(ProjectName("cowsay"))
    assert [Version("5"), Version("6")] == sorted(locked_versions)

    return lock_file


@pytest.fixture
def pex_root(tmpdir):
    # type: (Tempdir) -> str
    return tmpdir.join("pex-root")


@pytest.fixture
def split_requirements_by_python_version_lock(
    tmpdir,  # type: Tempdir
    pex_root,  # type: str
):
    # type: (...) -> str

    lock_file = tmpdir.join("lock.json")
    run_pex3(
        "lock",
        "create",
        "--pex-root",
        pex_root,
        "--style",
        "universal",
        "cowsay<6; python_version < '3'",
        "cowsay==6; python_version >= '3'",
        "--indent",
        "2",
        "-o",
        lock_file,
    ).assert_success()
    return assert_split_cowsay_lock(lock_file)


PYTHON2 = sys.executable if sys.version_info[0] == 2 else ensure_python_interpreter(PY27)
PYTHON3 = sys.executable if sys.version_info[0] == 3 else ensure_python_interpreter(PY311)
PYTHON3_VERSION_STR = PythonInterpreter.from_binary(PYTHON3).python
PLATFORM_SYSTEM = targets.current().marker_environment.platform_system


def test_sync_split_universal_lock(
    tmpdir,  # type: Tempdir
    split_requirements_by_python_version_lock,  # type: str
    pex_root,  # type: str
):
    # type: (...) -> None

    result = run_pex3(
        "lock",
        "sync",
        "--pex-root",
        pex_root,
        "--style",
        "universal",
        "cowsay<6; python_version < '3'",
        "cowsay==6; python_version >= '3'",
        "--indent",
        "2",
        "--lock",
        split_requirements_by_python_version_lock,
        "--dry-run",
        "check",
    )
    result.assert_success()
    assert 2 == len(
        [
            line
            for line in result.error.splitlines()
            if "No updates for lock generated by universal " in line
        ]
    )
