from types import SimpleNamespace

from unittest.mock import AsyncMock

import pytest

from src.models.approval import RiskLevel
from src.services.executor import OperationType
from src.services.approval_execution import ApprovalExecutionService


class _FakeAutoRepairRepo:
    def __init__(self) -> None:
        self.created: list[dict] = []

    async def list_by_incident(self, incident_id: str) -> list:
        return []

    async def create(self, **kwargs):
        self.created.append(kwargs)
        return SimpleNamespace(id="are-1", **kwargs)


@pytest.mark.asyncio
async def test_finalize_auto_approved_execution_persists_incident_link(monkeypatch):
    repo = _FakeAutoRepairRepo()
    timeline = SimpleNamespace(add_event=AsyncMock())
    incident_service = SimpleNamespace(resolve_incident=AsyncMock())
    write_km = AsyncMock()
    run_verify = AsyncMock()

    monkeypatch.setattr(
        "src.repositories.audit_log_repository.get_auto_repair_execution_repository",
        lambda: repo,
    )
    monkeypatch.setattr(
        "src.services.approval_execution.get_timeline_service",
        lambda: timeline,
    )
    monkeypatch.setattr(
        "src.services.incident_service.get_incident_service",
        lambda: incident_service,
    )
    monkeypatch.setattr(
        "src.core.feature_flags.aiops_flags",
        SimpleNamespace(is_sub_flag_enabled=lambda _: True),
    )
    monkeypatch.setattr(
        ApprovalExecutionService,
        "write_execution_result_to_km",
        write_km,
    )
    monkeypatch.setattr(
        ApprovalExecutionService,
        "_run_post_execution_verify",
        run_verify,
    )

    approval = SimpleNamespace(
        id="11111111-1111-1111-1111-111111111111",
        incident_id="INC-20260513-001",
        action="kubectl rollout restart deployment/api -n awoooi-prod",
        requested_by="auto_approve_rule_engine",
        matched_playbook_id="pb-auto-001",
        risk_level=RiskLevel.LOW,
    )

    await ApprovalExecutionService().finalize_auto_approved_execution(
        approval,
        success=True,
    )

    assert repo.created == [
        {
            "incident_id": "INC-20260513-001",
            "playbook_id": "pb-auto-001",
            "playbook_name": "approval_auto_execute:RESTART_DEPLOYMENT:api",
            "success": True,
            "executed_steps": ["kubectl rollout restart deployment/api -n awoooi-prod"],
            "error_message": None,
            "triggered_by": "auto_approve_rule_engine",
            "risk_level": "low",
        }
    ]
    timeline.add_event.assert_awaited_once()
    write_km.assert_awaited_once_with(approval, True, None)
    run_verify.assert_awaited_once()
    assert run_verify.await_args.kwargs["action_taken"].startswith(
        "auto_repair_playbook:pb-auto-001:RESTART_DEPLOYMENT:api"
    )
    incident_service.resolve_incident.assert_awaited_once_with("INC-20260513-001")


@pytest.mark.asyncio
async def test_finalize_auto_approved_execution_skips_no_action(monkeypatch):
    repo = _FakeAutoRepairRepo()
    write_km = AsyncMock()
    run_verify = AsyncMock()

    monkeypatch.setattr(
        "src.repositories.audit_log_repository.get_auto_repair_execution_repository",
        lambda: repo,
    )
    monkeypatch.setattr(
        ApprovalExecutionService,
        "write_execution_result_to_km",
        write_km,
    )
    monkeypatch.setattr(
        ApprovalExecutionService,
        "_run_post_execution_verify",
        run_verify,
    )

    approval = SimpleNamespace(
        id="22222222-2222-2222-2222-222222222222",
        incident_id="INC-20260513-002",
        action="NO_ACTION: observe only",
        requested_by="auto_approve_rule_engine",
        matched_playbook_id="pb-auto-002",
        risk_level=RiskLevel.LOW,
    )

    await ApprovalExecutionService().finalize_auto_approved_execution(
        approval,
        success=True,
    )

    assert repo.created == []
    write_km.assert_not_awaited()
    run_verify.assert_not_awaited()


@pytest.mark.asyncio
async def test_record_approved_repair_execution_persists_human_approved_trace(monkeypatch):
    repo = _FakeAutoRepairRepo()
    monkeypatch.setattr(
        "src.repositories.audit_log_repository.get_auto_repair_execution_repository",
        lambda: repo,
    )

    approval = SimpleNamespace(
        id="77777777-7777-7777-7777-777777777777",
        incident_id="INC-20260611-HUMAN",
        action="kubectl rollout restart deployment/api -n awoooi-prod",
        requested_by="OpenClaw (ollama_gcp_a)",
        matched_playbook_id="pb-human-001",
        risk_level=RiskLevel.MEDIUM,
    )

    await ApprovalExecutionService()._record_approved_repair_execution(
        approval=approval,
        success=True,
        error_message=None,
        operation_type=OperationType.RESTART_DEPLOYMENT,
        resource_name="api",
        namespace="awoooi-prod",
        duration_ms=1234,
    )

    assert repo.created == [
        {
            "incident_id": "INC-20260611-HUMAN",
            "playbook_id": "pb-human-001",
            "playbook_name": "approval_execute:RESTART_DEPLOYMENT:api",
            "success": True,
            "executed_steps": [
                "kubectl rollout restart deployment/api -n awoooi-prod"
            ],
            "error_message": None,
            "triggered_by": "human_approved",
            "risk_level": "medium",
            "execution_time_ms": 1234,
        }
    ]
