# [DEF:test_clean_release_v2_release_api:Module]
# @TIER: STANDARD
# @PURPOSE: API contract test scaffolding for clean release approval and publication endpoints.
# @LAYER: Domain
# @RELATION: IMPLEMENTS -> clean_release_v2_release_api_contracts

"""Contract tests for redesigned approval/publication API endpoints."""

from datetime import datetime, timezone
from uuid import uuid4

from fastapi import FastAPI
from fastapi.testclient import TestClient

from src.api.routes.clean_release_v2 import router as clean_release_v2_router
from src.dependencies import get_clean_release_repository
from src.models.clean_release import ComplianceReport, ReleaseCandidate
from src.services.clean_release.enums import CandidateStatus, ComplianceDecision


test_app = FastAPI()
test_app.include_router(clean_release_v2_router)
client = TestClient(test_app)


def _seed_candidate_and_passed_report() -> tuple[str, str]:
    repository = get_clean_release_repository()
    candidate_id = f"api-release-candidate-{uuid4()}"
    report_id = f"api-release-report-{uuid4()}"

    repository.save_candidate(
        ReleaseCandidate(
            id=candidate_id,
            version="1.0.0",
            source_snapshot_ref="git:sha-api-release",
            created_by="api-test",
            created_at=datetime.now(timezone.utc),
            status=CandidateStatus.CHECK_PASSED.value,
        )
    )
    repository.save_report(
        ComplianceReport(
            id=report_id,
            run_id=f"run-{uuid4()}",
            candidate_id=candidate_id,
            final_status=ComplianceDecision.PASSED.value,
            summary_json={"operator_summary": "ok", "violations_count": 0, "blocking_violations_count": 0},
            generated_at=datetime.now(timezone.utc),
            immutable=True,
        )
    )
    return candidate_id, report_id


def test_release_approve_and_publish_revoke_contract() -> None:
    """Contract for approve -> publish -> revoke lifecycle endpoints."""
    candidate_id, report_id = _seed_candidate_and_passed_report()

    approve_response = client.post(
        f"/api/v2/clean-release/candidates/{candidate_id}/approve",
        json={"report_id": report_id, "decided_by": "api-test", "comment": "approved"},
    )
    assert approve_response.status_code == 200
    approve_payload = approve_response.json()
    assert approve_payload["status"] == "ok"
    assert approve_payload["decision"] == "APPROVED"

    publish_response = client.post(
        f"/api/v2/clean-release/candidates/{candidate_id}/publish",
        json={
            "report_id": report_id,
            "published_by": "api-test",
            "target_channel": "stable",
            "publication_ref": "rel-api-001",
        },
    )
    assert publish_response.status_code == 200
    publish_payload = publish_response.json()
    assert publish_payload["status"] == "ok"
    assert publish_payload["publication"]["status"] == "ACTIVE"

    publication_id = publish_payload["publication"]["id"]
    revoke_response = client.post(
        f"/api/v2/clean-release/publications/{publication_id}/revoke",
        json={"revoked_by": "api-test", "comment": "rollback"},
    )
    assert revoke_response.status_code == 200
    revoke_payload = revoke_response.json()
    assert revoke_payload["status"] == "ok"
    assert revoke_payload["publication"]["status"] == "REVOKED"


def test_release_reject_contract() -> None:
    """Contract for reject endpoint."""
    candidate_id, report_id = _seed_candidate_and_passed_report()

    reject_response = client.post(
        f"/api/v2/clean-release/candidates/{candidate_id}/reject",
        json={"report_id": report_id, "decided_by": "api-test", "comment": "rejected"},
    )
    assert reject_response.status_code == 200
    payload = reject_response.json()
    assert payload["status"] == "ok"
    assert payload["decision"] == "REJECTED"


# [/DEF:test_clean_release_v2_release_api:Module]