# [DEF:backend.tests.services.clean_release.test_report_builder:Module]
# @TIER: STANDARD
# @SEMANTICS: tests, clean-release, report-builder, counters
# @PURPOSE: Validate compliance report builder counter integrity and blocked-run constraints.
# @LAYER: Domain
# @RELATION: TESTS -> backend.src.services.clean_release.report_builder
# @INVARIANT: blocked run requires at least one blocking violation.

from datetime import datetime, timezone

import pytest

from src.models.clean_release import (
    CheckFinalStatus,
    ComplianceCheckRun,
    ComplianceViolation,
    ExecutionMode,
    ViolationCategory,
    ViolationSeverity,
)
from src.services.clean_release.report_builder import ComplianceReportBuilder
from src.services.clean_release.repository import CleanReleaseRepository


# [DEF:_terminal_run:Function]
# @PURPOSE: Build terminal/non-terminal run fixtures for report builder tests.
def _terminal_run(status: CheckFinalStatus) -> ComplianceCheckRun:
    return ComplianceCheckRun(
        check_run_id="check-1",
        candidate_id="2026.03.03-rc1",
        policy_id="policy-enterprise-clean-v1",
        started_at=datetime.now(timezone.utc),
        finished_at=datetime.now(timezone.utc),
        final_status=status,
        triggered_by="tester",
        execution_mode=ExecutionMode.TUI,
        checks=[],
    )
# [/DEF:_terminal_run:Function]


# [DEF:_blocking_violation:Function]
# @PURPOSE: Build a blocking violation fixture for blocked report scenarios.
def _blocking_violation() -> ComplianceViolation:
    return ComplianceViolation(
        violation_id="viol-1",
        check_run_id="check-1",
        category=ViolationCategory.EXTERNAL_SOURCE,
        severity=ViolationSeverity.CRITICAL,
        location="pypi.org",
        remediation="replace",
        blocked_release=True,
        detected_at=datetime.now(timezone.utc),
    )
# [/DEF:_blocking_violation:Function]


# [DEF:test_report_builder_blocked_requires_blocking_violations:Function]
# @PURPOSE: Verify BLOCKED run requires at least one blocking violation.
def test_report_builder_blocked_requires_blocking_violations():
    builder = ComplianceReportBuilder(CleanReleaseRepository())
    run = _terminal_run(CheckFinalStatus.BLOCKED)

    with pytest.raises(ValueError):
        builder.build_report_payload(run, [])
# [/DEF:test_report_builder_blocked_requires_blocking_violations:Function]


# [DEF:test_report_builder_blocked_with_two_violations:Function]
# @PURPOSE: Verify report builder generates conformant payload for a BLOCKED run with violations.
def test_report_builder_blocked_with_two_violations():
    builder = ComplianceReportBuilder(CleanReleaseRepository())
    run = _terminal_run(CheckFinalStatus.BLOCKED)
    v1 = _blocking_violation()
    v2 = _blocking_violation()
    v2.violation_id = "viol-2"
    v2.category = ViolationCategory.DATA_PURITY
    
    report = builder.build_report_payload(run, [v1, v2])
    
    assert report.check_run_id == run.check_run_id
    assert report.candidate_id == run.candidate_id
    assert report.final_status == CheckFinalStatus.BLOCKED
    assert report.violations_count == 2
    assert report.blocking_violations_count == 2
# [/DEF:test_report_builder_blocked_with_two_violations:Function]


# [DEF:test_report_builder_counter_consistency:Function]
# @PURPOSE: Verify violations counters remain consistent for blocking payload.
def test_report_builder_counter_consistency():
    builder = ComplianceReportBuilder(CleanReleaseRepository())
    run = _terminal_run(CheckFinalStatus.BLOCKED)
    report = builder.build_report_payload(run, [_blocking_violation()])

    assert report.violations_count == 1
    assert report.blocking_violations_count == 1
# [/DEF:test_report_builder_counter_consistency:Function]


# [DEF:test_missing_operator_summary:Function]
# @PURPOSE: Validate non-terminal run prevents operator summary/report generation.
def test_missing_operator_summary():
    builder = ComplianceReportBuilder(CleanReleaseRepository())
    run = _terminal_run(CheckFinalStatus.RUNNING)

    with pytest.raises(ValueError) as exc:
        builder.build_report_payload(run, [])

    assert "Cannot build report for non-terminal run" in str(exc.value)
# [/DEF:test_missing_operator_summary:Function]
# [/DEF:backend.tests.services.clean_release.test_report_builder:Module]
