# region TestReportBuilder [TYPE Module]
# @RELATION DEPENDS_ON ->[ReportBuilder]
# @SEMANTICS: tests, clean-release, report-builder, counters
# @PURPOSE: Validate compliance report builder counter integrity and blocked-run constraints.
# @LAYER Domain
# @INVARIANT  blocked run requires at least one blocking violation.

from datetime import UTC, datetime
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


# region _terminal_run [TYPE Function]
# @RELATION  BINDS_TO -> TestReportBuilder
# @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(UTC),
        finished_at=datetime.now(UTC),
        final_status=status,
        triggered_by="tester",
        execution_mode=ExecutionMode.TUI,
        checks=[],
    )


# endregion _terminal_run


# region _blocking_violation [TYPE Function]
# @RELATION  BINDS_TO -> TestReportBuilder
# @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(UTC),
    )


# endregion _blocking_violation


# region test_report_builder_blocked_requires_blocking_violations [TYPE Function]
# @RELATION  BINDS_TO -> TestReportBuilder
# @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, [])


# endregion test_report_builder_blocked_requires_blocking_violations


# region test_report_builder_blocked_with_two_violations [TYPE Function]
# @RELATION  BINDS_TO -> TestReportBuilder
# @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


# endregion test_report_builder_blocked_with_two_violations


# region test_report_builder_counter_consistency [TYPE Function]
# @RELATION  BINDS_TO -> TestReportBuilder
# @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


# endregion test_report_builder_counter_consistency


# region test_missing_operator_summary [TYPE Function]
# @RELATION  BINDS_TO -> TestReportBuilder
# @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)


# endregion test_missing_operator_summary
# endregion TestReportBuilder
