from datetime import UTC, datetime, timedelta
from types import SimpleNamespace
from uuid import UUID

from src.models.approval import (
    ApprovalRequest,
    ApprovalRequestResponse,
    ApprovalStatus,
    RiskLevel,
)
from src.services.approval_db import approval_record_to_request
from src.services.heartbeat_report_service import (
    AlertPipelineStats,
    DbRedisStats,
    FlywheelStats,
    HeartbeatReport,
    HeartbeatReportService,
)


def test_approval_response_exposes_incident_delivery_and_playbook_fields():
    approval = ApprovalRequest(
        id=UUID("11111111-1111-1111-1111-111111111111"),
        action="kubectl rollout restart deployment/awoooi-api",
        description="manual gate",
        risk_level=RiskLevel.MEDIUM,
        requested_by="OpenClaw",
        required_signatures=1,
        incident_id="INC-20260531-VISIBLE",
        matched_playbook_id="PB-20260531-VISIBLE",
        telegram_message_id=98765,
        telegram_chat_id=-1001234567890,
    )

    response = ApprovalRequestResponse.from_approval(approval)

    assert response.incident_id == "INC-20260531-VISIBLE"
    assert response.matched_playbook_id == "PB-20260531-VISIBLE"
    assert response.telegram_message_id == 98765
    assert response.telegram_chat_id == -1001234567890


def test_approval_db_converter_preserves_incident_and_telegram_fields():
    now = datetime.now(UTC)
    record = SimpleNamespace(
        id="22222222-2222-2222-2222-222222222222",
        action="OBSERVE",
        description="[LLM Failed] observe only",
        status=ApprovalStatus.PENDING,
        risk_level=RiskLevel.MEDIUM,
        blast_radius={
            "affected_pods": 0,
            "estimated_downtime": "0",
            "related_services": [],
            "data_impact": "none",
        },
        dry_run_checks=[],
        required_signatures=1,
        current_signatures=0,
        signatures=[],
        requested_by="OpenClaw (fallback)",
        created_at=now,
        expires_at=now + timedelta(hours=1),
        resolved_at=None,
        rejection_reason=None,
        extra_metadata={"source": "fallback"},
        fingerprint="abc123",
        hit_count=2,
        last_seen_at=now,
        incident_id="INC-20260531-LEGACY",
        matched_playbook_id="PB-20260531-LEGACY",
        telegram_message_id=45678,
        telegram_chat_id=-1001234567890,
    )

    approval = approval_record_to_request(record)

    assert approval.incident_id == "INC-20260531-LEGACY"
    assert approval.matched_playbook_id == "PB-20260531-LEGACY"
    assert approval.telegram_message_id == 45678
    assert approval.telegram_chat_id == -1001234567890


def _report_with_pipeline(stats: AlertPipelineStats) -> HeartbeatReport:
    return HeartbeatReport(
        timestamp=datetime.now(UTC),
        flywheel=FlywheelStats(playbook_count=1),
        db_redis=DbRedisStats(db_ok=True, db_status="ok", redis_ok=True, redis_status="ok"),
        alert_pipeline=stats,
    )


def test_heartbeat_does_not_warn_when_pending_backlog_is_observe_only():
    report = _report_with_pipeline(
        AlertPipelineStats(
            total_24h=25,
            pending_approval=21,
            pending_actionable=1,
            pending_observe_only=20,
        )
    )

    warnings = HeartbeatReportService()._build_warnings(report)

    assert not any("待人工審核" in warning for warning in warnings)
    assert not any("PENDING 積壓" in warning for warning in warnings)


def test_heartbeat_warns_with_frontend_route_for_actionable_backlog():
    report = _report_with_pipeline(
        AlertPipelineStats(
            total_24h=25,
            pending_approval=21,
            pending_actionable=11,
            pending_observe_only=10,
        )
    )

    warnings = HeartbeatReportService()._build_warnings(report)

    assert any("/awooop/approvals" in warning for warning in warnings)
    assert any("觀察類 10" in warning for warning in warnings)
