# #region Test.CleanRelease.AuditService [C:3] [TYPE Module] [SEMANTICS test,clean-release,audit]
# @BRIEF Tests for audit_service.py — audit_preparation, audit_check_run, audit_violation, audit_report.
# @RELATION BINDS_TO -> [AuditService]

from pathlib import Path
import sys

sys.path.insert(0, str(Path(__file__).parent.parent.parent.parent / "src"))

from unittest.mock import MagicMock, patch
import pytest


# #region TestAuditPreparation [C:2] [TYPE Module]
class TestAuditPreparation:
    def test_audit_preparation_logs_and_appends(self):
        from src.services.clean_release.audit_service import audit_preparation
        repo = MagicMock()
        repo.append_audit_event = MagicMock()

        with patch("src.services.clean_release.audit_service.logger") as mock_logger:
            audit_preparation(
                candidate_id="cand-1",
                status="PREPARED",
                repository=repo,
                actor="tester",
            )
            mock_logger.reason.assert_called_once()
            repo.append_audit_event.assert_called_once()
            event = repo.append_audit_event.call_args[0][0]
            assert event["action"] == "PREPARATION"
            assert event["candidate_id"] == "cand-1"
            assert event["actor"] == "tester"
            assert event["status"] == "PREPARED"

    def test_audit_preparation_no_repo(self):
        from src.services.clean_release.audit_service import audit_preparation
        with patch("src.services.clean_release.audit_service.logger") as mock_logger:
            audit_preparation(candidate_id="cand-2", status="FAILED")
            mock_logger.reason.assert_called_once()


# #endregion TestAuditPreparation


# #region TestAuditCheckRun [C:2] [TYPE Module]
class TestAuditCheckRun:
    def test_audit_check_run_logs_and_appends(self):
        from src.services.clean_release.audit_service import audit_check_run
        repo = MagicMock()
        repo.append_audit_event = MagicMock()

        with patch("src.services.clean_release.audit_service.logger") as mock_logger:
            audit_check_run(
                check_run_id="run-1",
                final_status="COMPLIANT",
                repository=repo,
                candidate_id="cand-1",
                actor="admin",
            )
            mock_logger.reflect.assert_called_once()
            repo.append_audit_event.assert_called_once()
            event = repo.append_audit_event.call_args[0][0]
            assert event["action"] == "CHECK_RUN"
            assert event["run_id"] == "run-1"
            assert event["candidate_id"] == "cand-1"

    def test_audit_check_run_no_candidate(self):
        from src.services.clean_release.audit_service import audit_check_run
        repo = MagicMock()
        repo.append_audit_event = MagicMock()

        with patch("src.services.clean_release.audit_service.logger") as mock_logger:
            audit_check_run(
                check_run_id="run-2",
                final_status="BLOCKED",
                repository=repo,
            )
            repo.append_audit_event.assert_called_once()
            event = repo.append_audit_event.call_args[0][0]
            assert event["candidate_id"] is None


# #endregion TestAuditCheckRun


# #region TestAuditViolation [C:2] [TYPE Module]
class TestAuditViolation:
    def test_audit_violation_logs_explore(self):
        """Cover audit_violation lines 79-82."""
        from src.services.clean_release.audit_service import audit_violation
        repo = MagicMock()
        repo.append_audit_event = MagicMock()

        with patch("src.services.clean_release.audit_service.logger") as mock_logger:
            audit_violation(
                run_id="run-1",
                stage_name="DATA_PURITY",
                code="POL001",
                repository=repo,
                candidate_id="cand-1",
                actor="tester",
            )
            mock_logger.explore.assert_called_once()
            repo.append_audit_event.assert_called_once()
            event = repo.append_audit_event.call_args[0][0]
            assert event["action"] == "VIOLATION"
            assert event["run_id"] == "run-1"
            assert event["stage_name"] == "DATA_PURITY"
            assert event["code"] == "POL001"

    def test_audit_violation_no_repo(self):
        """audit_violation without repository does not crash."""
        from src.services.clean_release.audit_service import audit_violation
        with patch("src.services.clean_release.audit_service.logger") as mock_logger:
            audit_violation(
                run_id="run-2",
                stage_name="SOURCE_ISOLATION",
                code="EXT001",
            )
            mock_logger.explore.assert_called_once()


# #endregion TestAuditViolation


# #region TestAuditReport [C:2] [TYPE Module]
class TestAuditReport:
    def test_audit_report_logs_and_appends(self):
        from src.services.clean_release.audit_service import audit_report
        repo = MagicMock()
        repo.append_audit_event = MagicMock()

        with patch("src.services.clean_release.audit_service.logger") as mock_logger:
            audit_report(
                report_id="report-1",
                candidate_id="cand-1",
                repository=repo,
                run_id="run-1",
                actor="tester",
            )
            mock_logger.explore.assert_called_once()
            repo.append_audit_event.assert_called_once()
            event = repo.append_audit_event.call_args[0][0]
            assert event["action"] == "REPORT"
            assert event["report_id"] == "report-1"

    def test_audit_report_no_repo_does_not_crash(self):
        from src.services.clean_release.audit_service import audit_report
        with patch("src.services.clean_release.audit_service.logger") as mock_logger:
            audit_report(
                report_id="report-2",
                candidate_id="cand-2",
            )
            mock_logger.explore.assert_called_once()


# #endregion TestAuditReport

# #endregion Test.CleanRelease.AuditService
