"""Tests for version handling."""

import os
from unittest import mock

import pytest

from polytropos.build.primitives import build_full_version, get_odoo_release


class TestBuildFullVersion:
    """Tests for version string building."""

    @pytest.mark.parametrize(
        "module_version,release,expected",
        [
            ("1.0.0", "17.0", "17.0.1.0.0"),
            ("1.2.3", "18.0", "18.0.1.2.3"),
            ("2.1.0", "16.0", "16.0.2.1.0"),
            ("1.0.0", "19.0", "19.0.1.0.0"),
            ("1.2.3.4", "17.0", "17.0.1.2.3.4"),
            ("1.2.3.4.5", "17.0", "17.0.1.2.3.4.5"),
            ("10.20.30.40.50.60", "18.0", "18.0.10.20.30.40.50.60"),
        ],
    )
    def test_version_building(self, module_version, release, expected):
        """Test that module version is combined with Odoo release correctly."""
        result = build_full_version(module_version, release)
        assert result == expected

    @pytest.mark.parametrize(
        "module_version,release",
        [
            ("1.0", "17.0"),
            ("1", "17.0"),
            ("2", "18.0"),
            ("1.2", "17.0"),
        ],
    )
    def test_version_too_few_components_raises(self, module_version, release):
        """Test that module version with fewer than 3 components raises ValueError."""
        with pytest.raises(ValueError, match="must have at least 3 components"):
            build_full_version(module_version, release)


class TestResolutionOrder:
    """Tests for Odoo release resolution order."""

    def test_config_settings_takes_precedence(self):
        """Test that config_settings takes precedence over env var."""
        with mock.patch.dict(os.environ, {"ODOO_RELEASE": "16.0"}):
            result = get_odoo_release({"odoo_release": "18.0"})
            assert result == "18.0"

    def test_env_var_when_no_config_settings(self):
        """Test that env var is used when no config_settings."""
        with mock.patch.dict(os.environ, {"ODOO_RELEASE": "17.0"}):
            result = get_odoo_release()
            assert result == "17.0"

    def test_env_var_when_config_settings_empty(self):
        """Test that env var is used when config_settings is empty."""
        with mock.patch.dict(os.environ, {"ODOO_RELEASE": "17.0"}):
            result = get_odoo_release({})
            assert result == "17.0"

    def test_none_when_no_source_available(self):
        """Test that ValueError is raised when no release source is available."""
        with (
            mock.patch.dict(os.environ, {}, clear=True),
            pytest.raises(ValueError, match="Odoo release not specified"),
        ):
            get_odoo_release()

    def test_odoo_release_attribute_missing(self, mock_odoo):
        """Test that missing odoo.release.series attribute is handled gracefully."""
        del mock_odoo.release.series

        with mock.patch.dict(os.environ, {}, clear=True):
            with pytest.raises(ValueError, match="Odoo release not specified"):
                get_odoo_release()

    def test_odoo_release_from_import(self, mock_odoo):
        """Test that odoo.release.series is used when available."""
        mock_odoo.release.series = "18.0"

        with mock.patch.dict(os.environ, {}, clear=True):
            result = get_odoo_release()
            assert result == "18.0"

    def test_config_settings_release_is_stringified(self):
        """Test that config_settings release value is converted to string."""
        result = get_odoo_release({"odoo_release": 17})  # type: ignore[arg-type]
        assert result == "17"

    def test_resolution_priority_config_over_env(self):
        """Test that config_settings has highest priority."""
        with mock.patch.dict(os.environ, {"ODOO_RELEASE": "16.0"}):
            result = get_odoo_release({"odoo_release": "19.0"})
            assert result == "19.0"

    def test_resolution_priority_env_over_odoo_import(self, mock_odoo):
        """Test that env var has higher priority than odoo import."""
        mock_odoo.release.series = "18.0"

        with mock.patch.dict(os.environ, {"ODOO_RELEASE": "17.0"}):
            result = get_odoo_release()
            assert result == "17.0"
