# #region TestCleanReleaseApi [TYPE Module] [C:3] [SEMANTICS tests, api, clean-release, checks, reports]
# @RELATION BINDS_TO -> SrcRoot
# @BRIEF Contract tests for clean release checks and reports endpoints.
# @LAYER Domain
# @INVARIANT  API returns deterministic payload shapes for checks and reports.
from datetime import UTC, datetime

from fastapi.testclient import TestClient

from src.app import app
from src.dependencies import get_clean_release_repository
from src.models.clean_release import (
    CheckFinalStatus,
    CleanProfilePolicy,
    ComplianceReport,
    ProfileType,
    ReleaseCandidate,
    ReleaseCandidateStatus,
    ResourceSourceEntry,
    ResourceSourceRegistry,
)
from src.services.clean_release.repository import CleanReleaseRepository


# #region _repo_with_seed_data [TYPE Function]
# @RELATION BINDS_TO -> TestCleanReleaseApi
def _repo_with_seed_data() -> CleanReleaseRepository:
    repo = CleanReleaseRepository()
    repo.save_candidate(
        ReleaseCandidate(
            candidate_id="2026.03.03-rc1",
            version="2026.03.03",
            profile=ProfileType.ENTERPRISE_CLEAN,
            created_at=datetime.now(UTC),
            created_by="tester",
            source_snapshot_ref="git:abc123",
            status=ReleaseCandidateStatus.PREPARED,
        )
    )
    repo.save_registry(
        ResourceSourceRegistry(
            registry_id="registry-internal-v1",
            name="Internal",
            entries=[
                ResourceSourceEntry(
                    source_id="src-1",
                    host="repo.intra.company.local",
                    protocol="https",
                    purpose="artifact-repo",
                    enabled=True,
                )
            ],
            updated_at=datetime.now(UTC),
            updated_by="tester",
            status="active",
        )
    )
    repo.save_policy(
        CleanProfilePolicy(
            policy_id="policy-enterprise-clean-v1",
            policy_version="1.0.0",
            active=True,
            prohibited_artifact_categories=["test-data"],
            required_system_categories=["system-init"],
            external_source_forbidden=True,
            internal_source_registry_ref="registry-internal-v1",
            effective_from=datetime.now(UTC),
            profile=ProfileType.ENTERPRISE_CLEAN,
        )
    )
    return repo
# #endregion _repo_with_seed_data
# #region test_start_check_and_get_status_contract [TYPE Function]
# @RELATION BINDS_TO -> TestCleanReleaseApi
# @BRIEF Validate checks start endpoint returns expected identifiers and status endpoint reflects the same run.
def test_start_check_and_get_status_contract():
    repo = _repo_with_seed_data()
    app.dependency_overrides[get_clean_release_repository] = lambda: repo
    try:
        client = TestClient(app)
        start = client.post(
            "/api/clean-release/checks",
            json={
                "candidate_id": "2026.03.03-rc1",
                "profile": "enterprise-clean",
                "execution_mode": "tui",
                "triggered_by": "tester",
            },
        )
        assert start.status_code == 202
        payload = start.json()
        assert set(["check_run_id", "candidate_id", "status", "started_at"]).issubset(
            payload.keys()
        )
        check_run_id = payload["check_run_id"]
        status_resp = client.get(f"/api/clean-release/checks/{check_run_id}")
        assert status_resp.status_code == 200
        status_payload = status_resp.json()
        assert status_payload["check_run_id"] == check_run_id
        assert "final_status" in status_payload
        assert "checks" in status_payload
    finally:
        app.dependency_overrides.clear()
# #endregion test_start_check_and_get_status_contract
# #region test_get_report_not_found_returns_404 [TYPE Function]
# @RELATION BINDS_TO -> TestCleanReleaseApi
# @BRIEF Validate reports endpoint returns 404 for an unknown report identifier.
def test_get_report_not_found_returns_404():
    repo = _repo_with_seed_data()
    app.dependency_overrides[get_clean_release_repository] = lambda: repo
    try:
        client = TestClient(app)
        resp = client.get("/api/clean-release/reports/unknown-report")
        assert resp.status_code == 404
    finally:
        app.dependency_overrides.clear()
# #endregion test_get_report_not_found_returns_404
# #region test_get_report_success [TYPE Function]
# @RELATION BINDS_TO -> TestCleanReleaseApi
# @BRIEF Validate reports endpoint returns persisted report payload for an existing report identifier.
def test_get_report_success():
    repo = _repo_with_seed_data()
    report = ComplianceReport(
        report_id="rep-1",
        check_run_id="run-1",
        candidate_id="2026.03.03-rc1",
        generated_at=datetime.now(UTC),
        final_status=CheckFinalStatus.COMPLIANT,
        operator_summary="all systems go",
        structured_payload_ref="manifest-1",
        violations_count=0,
        blocking_violations_count=0,
    )
    repo.save_report(report)
    app.dependency_overrides[get_clean_release_repository] = lambda: repo
    try:
        client = TestClient(app)
        resp = client.get("/api/clean-release/reports/rep-1")
        assert resp.status_code == 200
        assert resp.json()["report_id"] == "rep-1"
    finally:
        app.dependency_overrides.clear()
# #endregion test_get_report_success
# #region test_prepare_candidate_api_success [TYPE Function]
# @RELATION BINDS_TO -> TestCleanReleaseApi
# @BRIEF Validate candidate preparation endpoint returns prepared status and manifest identifier on valid input.
def test_prepare_candidate_api_success():
    repo = _repo_with_seed_data()
    app.dependency_overrides[get_clean_release_repository] = lambda: repo
    try:
        client = TestClient(app)
        response = client.post(
            "/api/clean-release/candidates/prepare",
            json={
                "candidate_id": "2026.03.03-rc1",
                "artifacts": [
                    {"path": "file1.txt", "category": "system-init", "reason": "core"}
                ],
                "sources": ["repo.intra.company.local"],
                "operator_id": "operator-1",
            },
        )
        assert response.status_code == 200
        data = response.json()
        assert data["status"] == "prepared"
        assert "manifest_id" in data
    finally:
        app.dependency_overrides.clear()
# #endregion test_prepare_candidate_api_success
# #endregion TestCleanReleaseApi
