import re
import unittest
from pathlib import Path


ACTION_YAML = Path(__file__).resolve().parents[1] / "action.yml"


def step_block(source: str, name: str) -> str:
    pattern = rf"    - name: {re.escape(name)}\n(?P<body>.*?)(?=\n    - name:|\Z)"
    match = re.search(pattern, source, re.DOTALL)
    if match is None:
        raise AssertionError(f"missing action step: {name}")
    return match.group("body")


class TestTestFlightVersionSlotWiring(unittest.TestCase):
    @classmethod
    def setUpClass(cls) -> None:
        cls.source = ACTION_YAML.read_text(encoding="utf-8")

    def test_opt_out_is_backward_compatible(self) -> None:
        self.assertRegex(
            self.source,
            r"(?m)^  manage-app-store-version:\n(?:    .*\n)*?    default: \"true\"$",
        )

    def test_opt_out_skips_store_version_but_keeps_build_number(self) -> None:
        store_slot = step_block(self.source, "Resolve App Store version slot (REUSE or CREATE)")
        testflight = step_block(self.source, "Resolve TestFlight build number")

        self.assertIn("inputs.manage-app-store-version == 'true'", store_slot)
        self.assertIn("inputs.manage-app-store-version == 'false'", testflight)
        self.assertIn(
            "APP_STORE_APPLE_ID: ${{ inputs.app-store-apple-id || env.CFG_APP_STORE_APPLE_ID }}",
            testflight,
        )
        self.assertIn("next_build_number.py", testflight)
        self.assertNotIn("manage_marketing_version.py", testflight)

    def test_metadata_requires_a_managed_store_version(self) -> None:
        detector = step_block(self.source, "Detect empty ASC metadata fields")
        whats_new = step_block(self.source, 'Set App Store "What\'s New"')

        self.assertIn("inputs.manage-app-store-version == 'true'", detector)
        self.assertIn("inputs.manage-app-store-version == 'true'", whats_new)

    def test_a_locked_store_version_ships_testflight_only(self) -> None:
        """The TESTFLIGHT_ONLY decision: the locked version is re-exported
        as MARKETING_VERSION (the build joins that train), no App Store
        version id is set, STORE_VERSION_LOCKED gates the metadata
        writers off, and the typed annotation carries the schema the
        panel parses."""
        store_slot = step_block(self.source, "Resolve App Store version slot (REUSE or CREATE)")
        self.assertIn('if [ "$DECISION" = "TESTFLIGHT_ONLY" ]; then', store_slot)
        self.assertIn('echo "STORE_VERSION_LOCKED=$EFFECTIVE_MV" >> "$GITHUB_ENV"', store_slot)
        self.assertIn('::notice title=store_version_locked::', store_slot)
        self.assertIn('\\"schema\\":\\"gowalk-cicd/store-version-locked.v1\\"', store_slot)
        for field in ("version", "state", "build_number"):
            self.assertIn(f'\\"{field}\\":', store_slot)
        # The locked branch re-exports MARKETING_VERSION exactly as the
        # auto-bump branch does, so Stamp Info.plist and Archive read it.
        locked = store_slot.split('if [ "$DECISION" = "TESTFLIGHT_ONLY" ]; then', 1)[1]
        locked = locked.split("elif", 1)[0]
        self.assertIn('echo "MARKETING_VERSION=$EFFECTIVE_MV" >> "$GITHUB_ENV"', locked)
        # Neither metadata writer runs against a locked slot: both scripts
        # require APP_STORE_VERSION_ID, which is empty here.
        detector = step_block(self.source, "Detect empty ASC metadata fields")
        whats_new = step_block(self.source, 'Set App Store "What\'s New"')
        self.assertIn("env.STORE_VERSION_LOCKED == ''", detector)
        self.assertIn("env.STORE_VERSION_LOCKED == ''", whats_new)


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