# #region TestDemoModeIsolation [C:2] [TYPE Module]
# @SEMANTICS: clean-release, demo-mode, isolation, namespace, repository
# @PURPOSE: Verify demo and real mode namespace isolation contracts before TUI integration.
# @LAYER Tests
# @RELATION  DEPENDS_ON -> [DemoDataService]

from __future__ import annotations

from datetime import UTC, datetime

from src.models.clean_release import ReleaseCandidate
from src.services.clean_release.demo_data_service import (
    build_namespaced_id,
    create_isolated_repository,
    resolve_namespace,
)


# #region test_resolve_namespace_separates_demo_and_real [C:2] [TYPE Function]
# @RELATION  BINDS_TO -> TestDemoModeIsolation
# @PURPOSE: Ensure namespace resolver returns deterministic and distinct namespaces.
# @PRE: Mode names are provided as user/runtime strings.
# @POST: Demo and real namespaces are different and stable.
def test_resolve_namespace_separates_demo_and_real() -> None:
    demo = resolve_namespace("demo")
    real = resolve_namespace("real")

    assert demo == "clean-release:demo"
    assert real == "clean-release:real"
    assert demo != real
# #endregion test_resolve_namespace_separates_demo_and_real


# #region test_build_namespaced_id_prevents_cross_mode_collisions [C:2] [TYPE Function]
# @RELATION  BINDS_TO -> TestDemoModeIsolation
# @PURPOSE: Ensure ID generation prevents demo/real collisions for identical logical IDs.
# @PRE: Same logical candidate id is used in two different namespaces.
# @POST: Produced physical IDs differ by namespace prefix.
def test_build_namespaced_id_prevents_cross_mode_collisions() -> None:
    logical_id = "2026.03.09-rc1"
    demo_id = build_namespaced_id(resolve_namespace("demo"), logical_id)
    real_id = build_namespaced_id(resolve_namespace("real"), logical_id)

    assert demo_id != real_id
    assert demo_id.startswith("clean-release:demo::")
    assert real_id.startswith("clean-release:real::")
# #endregion test_build_namespaced_id_prevents_cross_mode_collisions


# #region test_create_isolated_repository_keeps_mode_data_separate [C:2] [TYPE Function]
# @RELATION  BINDS_TO -> TestDemoModeIsolation
# @PURPOSE: Verify demo and real repositories do not leak state across mode boundaries.
# @PRE: Two repositories are created for distinct modes.
# @POST: Candidate mutations in one mode are not visible in the other mode.
def test_create_isolated_repository_keeps_mode_data_separate() -> None:
    demo_repo = create_isolated_repository("demo")
    real_repo = create_isolated_repository("real")

    demo_candidate_id = build_namespaced_id(resolve_namespace("demo"), "candidate-1")
    real_candidate_id = build_namespaced_id(resolve_namespace("real"), "candidate-1")

    demo_repo.save_candidate(
        ReleaseCandidate(
            id=demo_candidate_id,
            version="1.0.0",
            source_snapshot_ref="git:sha-demo",
            created_by="demo-operator",
            created_at=datetime.now(UTC),
            status="DRAFT",
        )
    )
    real_repo.save_candidate(
        ReleaseCandidate(
            id=real_candidate_id,
            version="1.0.0",
            source_snapshot_ref="git:sha-real",
            created_by="real-operator",
            created_at=datetime.now(UTC),
            status="DRAFT",
        )
    )

    assert demo_repo.get_candidate(demo_candidate_id) is not None
    assert demo_repo.get_candidate(real_candidate_id) is None
    assert real_repo.get_candidate(real_candidate_id) is not None
    assert real_repo.get_candidate(demo_candidate_id) is None
# #endregion test_create_isolated_repository_keeps_mode_data_separate

# #endregion TestDemoModeIsolation
