# apps/api/tests/test_golden_regression.py
# 2026-04-28 ogt + Claude Sonnet 4.6 — P3.2.4 黃金回歸測試集
"""
30 個黃金測試案例，保護 classify_alert_early() 邏輯不退步。
涵蓋 10 類告警場景。

函數簽章：
    classify_alert_early(alertname, severity, labels=None, age_hours=0.0)
    -> tuple[str, str]  # (alert_category, notification_type)
"""
from __future__ import annotations

from src.services.incident_service import classify_alert_early


class TestKubernetes:
    def test_pod_crash_looping(self):
        cat, ntype = classify_alert_early("PodCrashLooping", "critical")
        assert cat == "kubernetes" and ntype == "TYPE-3"

    def test_deploy_rollout_stuck(self):
        cat, ntype = classify_alert_early("DeployRolloutStuck", "warning")
        assert cat == "kubernetes" and ntype == "TYPE-3"

    def test_kube_node_not_ready(self):
        cat, ntype = classify_alert_early("KubeNodeNotReady", "critical")
        assert cat == "kubernetes" and ntype == "TYPE-3"

    def test_pod_oom_killed(self):
        cat, ntype = classify_alert_early("PodOOMKilled", "warning")
        assert cat == "kubernetes" and ntype == "TYPE-3"

    def test_node_memory_pressure(self):
        cat, ntype = classify_alert_early("NodeMemoryPressure", "warning")
        assert cat == "kubernetes" and ntype == "TYPE-3"


class TestHostResource:
    def test_host_high_cpu_load(self):
        cat, ntype = classify_alert_early("HostHighCpuLoad", "critical")
        assert cat == "host_resource" and ntype == "TYPE-3"

    def test_host_high_memory(self):
        cat, ntype = classify_alert_early("HostHighMemory", "warning")
        assert cat == "host_resource" and ntype == "TYPE-3"

    def test_host_disk_space_full(self):
        cat, ntype = classify_alert_early("HostDiskSpaceFull", "critical")
        assert cat == "host_resource" and ntype == "TYPE-3"

    def test_systemd_runner_watchdog_is_not_heartbeat(self):
        cat, ntype = classify_alert_early("SystemdRunnerWatchdogEnabled", "warning")
        assert cat == "host_resource" and ntype == "TYPE-3"


class TestHighCpuVariants:
    """HighCPU* prefix 規則覆蓋"""
    def test_high_cpu_prefix(self):
        cat, ntype = classify_alert_early("HighCPUUsage", "critical")
        assert cat == "host_resource" and ntype == "TYPE-3"

    def test_high_memory_prefix(self):
        cat, ntype = classify_alert_early("HighMemoryPressure", "warning")
        assert cat == "host_resource" and ntype == "TYPE-3"


class TestBackup:
    def test_host_backup_failed_fresh(self):
        """< 24h 備份失敗 → TYPE-1（pure info）"""
        cat, ntype = classify_alert_early("HostBackupFailed", "warning", age_hours=10.0)
        assert cat == "backup" and ntype == "TYPE-1"

    def test_host_backup_failed_stale_upgrade(self):
        """> 24h 備份失敗 → 升級為 TYPE-3（P0 故障）"""
        cat, ntype = classify_alert_early("HostBackupFailed", "warning", age_hours=25.0)
        assert cat == "backup_failure" and ntype == "TYPE-3"

    def test_host_backup_stale_upgrade(self):
        cat, ntype = classify_alert_early("HostBackupStale", "warning", age_hours=30.0)
        assert cat == "backup_failure" and ntype == "TYPE-3"

    def test_backup_restore_test_not_upgraded(self):
        """BackupRestoreTestFailed 不受 age 升級影響"""
        cat, ntype = classify_alert_early("BackupRestoreTestFailed", "warning", age_hours=48.0)
        assert ntype == "TYPE-1"


class TestDatabase:
    def test_postgres_connections_high(self):
        cat, ntype = classify_alert_early("PostgreSQLConnectionsHigh", "warning")
        assert cat == "database" and ntype == "TYPE-3"

    def test_postgres_disk_growth_rate(self):
        cat, ntype = classify_alert_early("PostgreSQLDiskGrowthRate", "warning")
        assert cat == "database" and ntype == "TYPE-3"

    def test_redis_memory_full(self):
        cat, ntype = classify_alert_early("RedisMemoryFull", "critical")
        assert cat == "database" and ntype == "TYPE-3"


class TestInfoAndHeartbeat:
    def test_severity_info_is_type1(self):
        _, ntype = classify_alert_early("SomeAlert", "info")
        assert ntype == "TYPE-1"

    def test_severity_none_is_type1(self):
        _, ntype = classify_alert_early("SomeAlert", "none")
        assert ntype == "TYPE-1"

    def test_watchdog_heartbeat(self):
        cat, ntype = classify_alert_early("Watchdog", "warning")
        assert cat == "backup" and ntype == "TYPE-1"

    def test_deadmansswitch(self):
        cat, ntype = classify_alert_early("DeadMansSwitch", "critical")
        assert cat == "backup" and ntype == "TYPE-1"


class TestConfigDrift:
    def test_configuration_drift(self):
        cat, ntype = classify_alert_early("ConfigurationDrift", "warning")
        assert cat == "config_drift" and ntype == "TYPE-4D"

    def test_kube_config_drift(self):
        cat, ntype = classify_alert_early("KubeConfigDrift", "critical")
        assert cat == "config_drift" and ntype == "TYPE-4D"


class TestFlywheelHealth:
    def test_auto_repair_low_success(self):
        cat, ntype = classify_alert_early("AutoRepairLowSuccessRate", "critical")
        assert cat == "flywheel_health" and ntype == "TYPE-8M"

    def test_ollama_down(self):
        cat, ntype = classify_alert_early("OllamaDown", "critical")
        assert cat == "flywheel_health" and ntype == "TYPE-8M"


class TestSecops:
    def test_unauthorized_ssh(self):
        cat, ntype = classify_alert_early("UnauthorizedSSH", "critical")
        assert cat == "secops" and ntype == "TYPE-5S"

    def test_pod_abnormal_activity(self):
        cat, ntype = classify_alert_early("PodAbnormalActivity", "critical")
        assert cat == "secops" and ntype == "TYPE-5S"


class TestDevopsAndExternal:
    def test_gitea_down(self):
        cat, ntype = classify_alert_early("GiteaDown", "critical")
        assert cat == "devops_tool" and ntype == "TYPE-3"

    def test_mowoo_work_down(self):
        cat, ntype = classify_alert_early("MoWoooWorkDown", "critical")
        assert cat == "external_site" and ntype == "TYPE-3"

    def test_minio_down(self):
        cat, ntype = classify_alert_early("MinIODown", "critical")
        assert cat == "storage" and ntype == "TYPE-3"


class TestAlertChainAndGeneral:
    def test_alert_chain_broken_alertmanager(self):
        cat, ntype = classify_alert_early("AlertChainBroken_Alertmanager", "critical")
        assert cat == "alertchain_health" and ntype == "TYPE-8M"

    def test_no_alerts_received(self):
        cat, ntype = classify_alert_early("NoAlertsReceived", "critical")
        assert cat == "alertchain_health" and ntype == "TYPE-8M"

    def test_unknown_alert_falls_to_general(self):
        cat, ntype = classify_alert_early("SomeBrandNewUnknownAlert2026", "warning")
        assert cat == "general" and ntype == "TYPE-3"
