#!/usr/bin/env python3
"""
Tests for the ground-truth cross-check error message produced by
``assert_target_meets_floor``.

Covers the per-source breakdown surfaced in production (not
synthesized): when the binding floor comes from preReleaseVersions or
buildsViaPreRelease, the error message MUST attribute the floor to the
real source rather than emitting ``<none>``.

Extracted from ``test_mmv_floor_check.py`` in round 8 to keep each
test file under the 10-functions-per-file cap. The
``GroundTruthFloorTests`` and ``CombinedFloorTests`` classes still
live in ``test_mmv_floor_check.py``.
"""

from __future__ import annotations

import os
import sys
import unittest
from pathlib import Path
from unittest import mock

sys.path.insert(0, str(Path(__file__).resolve().parent))

import manage_marketing_version as mmv  # noqa: E402
import asc_build_history  # noqa: E402

from tests_common import (  # noqa: E402
    _assert_decide_exits,
    _assert_mentions_build_setting_source,
    _v,
)


def setUpModule() -> None:
    """Pin auto-bump to 'none' for the whole module.

    The cross-check tests assert the historical fail-on-floor error
    message text. With auto-bump enabled (the default 'patch'), the
    floor-violation path would auto-bump instead of failing, which
    is a different code path covered elsewhere."""
    global _ENV_PATCH
    _ENV_PATCH = mock.patch.dict(
        os.environ, {"MARKETING_VERSION_AUTO_BUMP": "none"}, clear=False,
    )
    _ENV_PATCH.start()


def tearDownModule() -> None:
    _ENV_PATCH.stop()


class GroundTruthCrossCheckMessageTests(unittest.TestCase):
    """The cross-check error message MUST name each source separately
    AND reference at least one build-setting source name."""

    def test_error_message_lists_each_source_max(self):
        per_source = {
            "appStoreVersions": "1.0",
            "preReleaseVersions": "1.0.4",
            "buildsViaPreRelease": None,
        }
        stderr = _assert_decide_exits(
            self, "1.0.0", [_v("1.0", "READY_FOR_SALE")],
            ground_truth="1.0.4", combined_floor="1.0.4",
            per_source=per_source,
        )
        self.assertIn("appStoreVersions", stderr)
        self.assertIn("preReleaseVersions", stderr)
        self.assertIn("buildsViaPreRelease", stderr)
        self.assertIn("1.0.4", stderr)
        _assert_mentions_build_setting_source(self, stderr)


class GroundTruthCrossCheckProductionPerSourceTests(unittest.TestCase):
    """Production seam: when the binding floor comes from preReleaseVersions
    or buildsViaPreRelease, the error message MUST surface the real
    per-source value (not synthesized `<none>`)."""

    def test_error_attributes_floor_to_prerelease_when_prerelease_pinned(self):
        per_source = {
            "appStoreVersions": "1.0",
            "preReleaseVersions": "1.1.1",
            "buildsViaPreRelease": None,
        }
        stderr = _assert_decide_exits(
            self, "1.0.0", [_v("1.0", "READY_FOR_SALE")],
            ground_truth=None, combined_floor="1.1.1",
            per_source=per_source,
        )
        self.assertIn("preReleaseVersions=1.1.1", stderr)
        self.assertNotIn("preReleaseVersions=<none>", stderr)
        self.assertIn("appStoreVersions=1.0", stderr)
        self.assertIn("1.1.1", stderr)
        _assert_mentions_build_setting_source(self, stderr)

    def test_error_attributes_floor_to_buildsViaPreRelease_when_builds_pinned(self):
        per_source = {
            "appStoreVersions": "1.0",
            "preReleaseVersions": None,
            "buildsViaPreRelease": "1.2.0",
        }
        stderr = _assert_decide_exits(
            self, "1.0.0", [_v("1.0", "READY_FOR_SALE")],
            ground_truth=None, combined_floor="1.2.0",
            per_source=per_source,
        )
        self.assertIn("buildsViaPreRelease=1.2.0", stderr)
        self.assertNotIn("buildsViaPreRelease=<none>", stderr)

    def test_get_combined_floor_returns_tuple_in_production(self):
        """The mmv.get_combined_floor wrapper now forwards (floor, per_source)
        from asc_version_fetch verbatim -- no synthesis."""
        with mock.patch.object(
                asc_build_history, "fetch_prerelease_versions",
                return_value=["1.1.1"]), \
                mock.patch.object(
                    asc_build_history, "fetch_builds_prerelease_versions",
                    return_value=[]):
            floor, per_source = mmv.get_combined_floor(
                "111", "tok",
                appstore_versions=[_v("1.0", "READY_FOR_SALE")],
            )
        self.assertEqual(floor, "1.1.1")
        self.assertEqual(per_source.get("preReleaseVersions"), "1.1.1")
        self.assertEqual(per_source.get("appStoreVersions"), "1.0")


if __name__ == "__main__":
    unittest.main()
