#!/usr/bin/env python3
"""
Tests for mmv_floor_check.py.

Covers:
  - ``get_combined_floor`` per-source breakdown across appStoreVersions,
    preReleaseVersions, and builds->preReleaseVersion.

``get_ground_truth_floor`` tests live in ``test_ground_truth_floor.py``
(round 11 split). The cross-check error-message tests live in
``test_mmv_floor_crosscheck.py`` (round 8 split).
``fetch_versions`` pagination / filter / limit / logging tests live in
``test_fetch_versions.py``. The /builds and /preReleaseVersions
fetcher tests live in ``test_asc_build_history.py`` and
``test_asc_builds_prerelease.py`` respectively.
"""

from __future__ import annotations

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
    _FakeResponse,
    _mk_prerelease_entry,
    _v,
)


def _builds_payload_with_prerelease(
    build_id: str, build_version: str, pr_id: str, pr_version: str,
) -> dict:
    """Combined-floor fixture: one /builds record paired with a
    preReleaseVersion include. Used to verify the combined-floor wiring
    consults the relationship rather than build.attributes.version."""
    return {
        "data": [{
            "id": build_id,
            "type": "builds",
            "attributes": {"version": build_version},
            "relationships": {
                "preReleaseVersion": {
                    "data": {"type": "preReleaseVersions", "id": pr_id},
                },
            },
        }],
        "included": [{
            "id": pr_id,
            "type": "preReleaseVersions",
            "attributes": {"version": pr_version, "platform": "IOS"},
        }],
        "links": {},
    }


class CombinedFloorTests(unittest.TestCase):
    """Combined floor spans appStoreVersions + preReleaseVersions +
    builds->preReleaseVersion. /v1/apps/{id}/builds.attributes.version
    (integer build number) is NOT consulted as a marketing version."""

    def test_combined_floor_excludes_builds_attributes_version(self):
        seen_paths: list[str] = []
        seen_params: list[dict | None] = []
        builds_payload = _builds_payload_with_prerelease(
            "b-42", "42", "pr-10", "1.0",
        )

        def fake_request(method, path, token, *, params=None, **_kw):
            seen_paths.append(path)
            seen_params.append(params)
            if "/builds" in path:
                return _FakeResponse(builds_payload)
            return _FakeResponse({"data": [], "links": {}})

        with mock.patch.object(
                asc_build_history, "request", side_effect=fake_request):
            floor, _ = mmv.get_combined_floor(
                "111", "tok",
                appstore_versions=[_v("1.0", "READY_FOR_SALE")],
            )

        self.assertTrue(seen_paths)
        self.assertTrue(any("/builds" in p for p in seen_paths))
        self.assertTrue(any("/preReleaseVersions" in p for p in seen_paths))
        builds_params = [
            p for p, path in zip(seen_params, seen_paths)
            if "/builds" in path and p is not None
        ]
        self.assertTrue(builds_params)
        self.assertEqual(builds_params[0].get("include"), "preReleaseVersion")
        self.assertEqual(floor, "1.0")
        self.assertFalse(
            hasattr(asc_build_history, "fetch_build_versions"),
            "asc_build_history.fetch_build_versions must stay removed",
        )

    def test_combined_floor_includes_prerelease(self):
        with mock.patch.object(
                asc_build_history, "fetch_prerelease_versions",
                return_value=["1.0.4"]), \
                mock.patch.object(
                    asc_build_history, "fetch_builds_prerelease_versions",
                    return_value=[]):
            floor, _ = mmv.get_combined_floor(
                "111", "tok",
                appstore_versions=[_v("1.0", "READY_FOR_SALE")],
            )
        self.assertEqual(floor, "1.0.4")

    def test_combined_floor_none_when_empty_everywhere(self):
        with mock.patch.object(
                asc_build_history, "fetch_prerelease_versions",
                return_value=[]), \
                mock.patch.object(
                    asc_build_history, "fetch_builds_prerelease_versions",
                    return_value=[]):
            floor, _ = mmv.get_combined_floor(
                "111", "tok", appstore_versions=[],
            )
        self.assertIsNone(floor)

    def test_combined_floor_unknown_endpoint_shape_doesnt_crash(self):
        def fake_request(method, path, token, *, params=None, **_kw):
            return _FakeResponse({
                "data": [
                    {"id": "null-version", "attributes": {}},
                    _mk_prerelease_entry("1.0.3", pid="good"),
                ],
                "links": {},
            })

        with mock.patch.object(
                asc_build_history, "request", side_effect=fake_request):
            prereleases = asc_build_history.fetch_prerelease_versions(
                "111", "tok"
            )
        self.assertEqual(prereleases, ["1.0.3"])


# GroundTruthCrossCheckMessageTests +
# GroundTruthCrossCheckProductionPerSourceTests were extracted to
# test_mmv_floor_crosscheck.py (round 8).
# ComputeNextVersionStrictnessTests was extracted to
# test_compute_next_version.py (round 8).
# GroundTruthFloorTests was extracted to test_ground_truth_floor.py
# (round 11).
# All three splits keep this file under the 10-functions-per-file cap.


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