import asyncio
from datetime import datetime

import pytest

from src.api.v1.webhooks import (
    _analyze_alertmanager_with_timeout,
    _should_bypass_alertmanager_llm,
    _should_use_alertmanager_rule_first,
)
from src.services.alertmanager_llm_guard import (
    ALERTMANAGER_LLM_INFLIGHT_LOCK_TTL_SECONDS,
    alertmanager_llm_inflight_key,
)
from src.services.decision_manager import (
    _is_host_layer_ssh_category,
    _is_non_k8s_host_category,
    _should_escalate_auto_approve_rejection,
)
from src.services.telegram_gateway import _format_resolved_guard_stamp


def test_host_resource_yaml_no_action_bypasses_llm():
    rule_response = {
        "rule_id": "host_resource_alert",
        "suggested_action": "NO_ACTION",
        "kubectl_command": "",
    }

    assert _should_bypass_alertmanager_llm(rule_response, "host_resource") is True


def test_generic_fallback_does_not_bypass_llm():
    rule_response = {
        "rule_id": "generic_fallback",
        "suggested_action": "NO_ACTION",
        "kubectl_command": "",
    }

    assert _should_bypass_alertmanager_llm(rule_response, "host_resource") is False


def test_non_host_category_does_not_bypass_llm():
    rule_response = {
        "rule_id": "host_resource_alert",
        "suggested_action": "NO_ACTION",
        "kubectl_command": "",
    }

    assert _should_bypass_alertmanager_llm(rule_response, "kubernetes") is False


def test_backup_failure_yaml_no_action_bypasses_llm():
    rule_response = {
        "rule_id": "host_backup_failed",
        "suggested_action": "NO_ACTION",
        "kubectl_command": "",
    }

    assert _should_bypass_alertmanager_llm(rule_response, "backup_failure") is True


def test_host_resource_ssh_rule_uses_rule_first():
    rule_response = {
        "rule_id": "host_resource_alert",
        "suggested_action": "SSH_DIAGNOSE",
        "kubectl_command": "ssh {host} 'df -h'",
    }

    assert _should_use_alertmanager_rule_first(rule_response, "host_resource") is True


def test_backup_failure_ssh_rule_uses_rule_first():
    rule_response = {
        "rule_id": "host_backup_failed",
        "suggested_action": "SSH_DIAGNOSE",
        "kubectl_command": "ssh {host} 'tail -80 backup.log'",
    }

    assert _should_use_alertmanager_rule_first(rule_response, "backup_failure") is True


def test_generic_fallback_does_not_use_rule_first():
    rule_response = {
        "rule_id": "generic_fallback",
        "suggested_action": "SSH_DIAGNOSE",
        "kubectl_command": "ssh {host} 'df -h'",
    }

    assert _should_use_alertmanager_rule_first(rule_response, "host_resource") is False


def test_manual_gate_reasons_escalate_to_emergency_intervention():
    assert _should_escalate_auto_approve_rejection("no_executable_action") is True
    assert _should_escalate_auto_approve_rejection("no_playbook") is True
    assert _should_escalate_auto_approve_rejection("critical_operation") is False


def test_backup_failure_routes_to_decision_ssh_before_kubectl_parser():
    assert _is_host_layer_ssh_category("backup_failure") is True
    assert _is_host_layer_ssh_category("host_resource") is True
    assert _is_host_layer_ssh_category("kubernetes") is False


def test_backup_failure_blocks_k8s_auto_execute():
    assert _is_non_k8s_host_category("backup_failure") is True
    assert _is_non_k8s_host_category("host_resource") is True
    assert _is_non_k8s_host_category("infrastructure") is False


def test_alertmanager_llm_inflight_lock_key_is_fingerprint_scoped():
    fingerprint = "abc123"

    assert alertmanager_llm_inflight_key(fingerprint) == "alertmanager:llm_inflight:abc123"
    assert ALERTMANAGER_LLM_INFLIGHT_LOCK_TTL_SECONDS == 600


@pytest.mark.asyncio
async def test_alertmanager_analysis_timeout_returns_fallback(monkeypatch):
    from src.api.v1 import webhooks as webhooks_module

    class SlowOpenClaw:
        async def analyze_alert(self, alert_context):
            await asyncio.sleep(1)
            return "unexpected"

    monkeypatch.setattr(webhooks_module, "ALERTMANAGER_BACKGROUND_AI_TIMEOUT_SECONDS", 0.01)

    result = await _analyze_alertmanager_with_timeout(
        SlowOpenClaw(),
        {"alertname": "AwoooPTimeoutCanary"},
        alert_id="alert-timeout",
        alertname="AwoooPTimeoutCanary",
    )

    assert result == (None, "fallback_timeout", "", None, "", 0, 0.0)


@pytest.mark.asyncio
async def test_alertmanager_analysis_error_returns_fallback():
    class BrokenOpenClaw:
        async def analyze_alert(self, alert_context):
            raise RuntimeError("provider chain failed")

    result = await _analyze_alertmanager_with_timeout(
        BrokenOpenClaw(),
        {"alertname": "AwoooPErrorCanary"},
        alert_id="alert-error",
        alertname="AwoooPErrorCanary",
    )

    assert result == (None, "fallback_error", "", None, "", 0, 0.0)


def test_resolved_guard_stamp_without_timestamp_is_clean():
    assert _format_resolved_guard_stamp(None) == "✅ 此事件已解決"


def test_resolved_guard_stamp_with_timestamp_formats_time():
    resolved_at = datetime(2026, 4, 25, 0, 2)

    assert (
        _format_resolved_guard_stamp(resolved_at)
        == "✅ 此事件已於 2026-04-25 00:02 解決"
    )
