"""
Tests for postmortem_draft_graph.

Mocks the GatewayClient — no real network calls.
"""

import asyncio
import base64
import json
import sys
from pathlib import Path
from unittest.mock import patch

import pytest

sys.path.insert(0, str(Path(__file__).parent.parent))
from tests.conftest import MockGatewayClient, _run


# ─── Mock data ────────────────────────────────────────────────────────────────

_INCIDENT_DATA = {
    "id": "inc_20260223_1000_abc123",
    "service": "router",
    "env": "prod",
    "severity": "P1",
    "status": "open",
    "title": "Router OOM",
    "summary": "Router pods running out of memory under high load",
    "started_at": "2026-02-23T10:00:00Z",
    "ended_at": None,
    "created_by": "sofiia",
    "events": [
        {"ts": "2026-02-23T10:01:00Z", "type": "note", "message": "Memory usage >90%"},
        {"ts": "2026-02-23T10:10:00Z", "type": "action", "message": "Restarted pods"},
    ],
    "artifacts": [],
}

_INCIDENT_WITH_TRIAGE = {
    **_INCIDENT_DATA,
    "artifacts": [
        {"kind": "triage_report", "format": "json", "path": "ops/incidents/inc_test/triage_report.json"},
    ],
}

_OVERVIEW_DATA = {
    "status": "degraded",
    "alerts": [{"name": "OOMKilled", "severity": "critical"}],
}

_HEALTH_DATA = {"status": "unhealthy", "error": "OOM"}

_KB_DATA = {"results": [
    {"path": "docs/runbooks/oom.md", "content": "## OOM Runbook\n- Check memory limits\n- Restart pods"}
]}


# ─── Tests ────────────────────────────────────────────────────────────────────

class TestPostmortemDraftGraph:
    """Happy path: incident exists, triage exists, postmortem generated."""

    def test_happy_path_with_triage(self):
        from app.graphs.postmortem_draft_graph import build_postmortem_draft_graph

        mock_gw = MockGatewayClient()
        mock_gw.register("oncall_tool", "incident_get", _INCIDENT_WITH_TRIAGE)
        mock_gw.register("oncall_tool", "incident_attach_artifact", {"artifact": {"path": "test", "sha256": "abc"}})
        mock_gw.register("oncall_tool", "incident_append_event", {"event": {"ts": "now", "type": "followup"}})

        graph = build_postmortem_draft_graph()

        with patch("app.graphs.postmortem_draft_graph.GatewayClient", return_value=mock_gw):
            result = _run(graph.ainvoke({
                "run_id": "gr_test_01",
                "agent_id": "sofiia",
                "workspace_id": "ws1",
                "user_id": "u1",
                "input": {
                    "incident_id": "inc_20260223_1000_abc123",
                    "service": "router",
                },
            }))

        assert result["graph_status"] == "succeeded"
        pm = result["result"]
        assert pm["incident_id"] == "inc_20260223_1000_abc123"
        assert pm["artifacts_count"] >= 2  # md + json
        assert "postmortem" in result["postmortem_md"].lower()

    def test_triage_missing_triggers_generation(self):
        """When incident has no triage artifact, the graph generates one."""
        from app.graphs.postmortem_draft_graph import build_postmortem_draft_graph

        mock_gw = MockGatewayClient()
        mock_gw.register("oncall_tool", "incident_get", _INCIDENT_DATA)  # no triage artifact
        mock_gw.register("observability_tool", "service_overview", _OVERVIEW_DATA)
        mock_gw.register("oncall_tool", "service_health", _HEALTH_DATA)
        mock_gw.register("kb_tool", "search", _KB_DATA)
        mock_gw.register("oncall_tool", "incident_attach_artifact", {"artifact": {"path": "t", "sha256": "x"}})
        mock_gw.register("oncall_tool", "incident_append_event", {"event": {}})

        graph = build_postmortem_draft_graph()

        with patch("app.graphs.postmortem_draft_graph.GatewayClient", return_value=mock_gw):
            result = _run(graph.ainvoke({
                "run_id": "gr_test_02",
                "agent_id": "sofiia",
                "workspace_id": "ws1",
                "user_id": "u1",
                "input": {"incident_id": "inc_20260223_1000_abc123"},
            }))

        assert result["graph_status"] == "succeeded"
        assert result.get("triage_was_generated") is True
        # Should have triage + postmortem artifacts (3 total)
        assert result["result"]["artifacts_count"] >= 2

    def test_incident_not_found_fails_gracefully(self):
        from app.graphs.postmortem_draft_graph import build_postmortem_draft_graph

        mock_gw = MockGatewayClient()
        mock_gw.register("oncall_tool", "incident_get", None, error="Incident not found")

        graph = build_postmortem_draft_graph()

        with patch("app.graphs.postmortem_draft_graph.GatewayClient", return_value=mock_gw):
            result = _run(graph.ainvoke({
                "run_id": "gr_test_03",
                "agent_id": "sofiia",
                "workspace_id": "ws1",
                "user_id": "u1",
                "input": {"incident_id": "inc_nonexistent"},
            }))

        assert result["graph_status"] == "failed"
        assert "not found" in (result.get("error") or "").lower()

    def test_missing_incident_id_fails(self):
        from app.graphs.postmortem_draft_graph import build_postmortem_draft_graph

        mock_gw = MockGatewayClient()
        graph = build_postmortem_draft_graph()

        with patch("app.graphs.postmortem_draft_graph.GatewayClient", return_value=mock_gw):
            result = _run(graph.ainvoke({
                "run_id": "gr_test_04",
                "agent_id": "sofiia",
                "workspace_id": "ws1",
                "user_id": "u1",
                "input": {},
            }))

        assert result["graph_status"] == "failed"
        assert "incident_id" in (result.get("validation_error") or "").lower()

    def test_gateway_error_on_followup_nonfatal(self):
        """If follow-up append fails, graph still succeeds."""
        from app.graphs.postmortem_draft_graph import build_postmortem_draft_graph

        mock_gw = MockGatewayClient()
        mock_gw.register("oncall_tool", "incident_get", _INCIDENT_WITH_TRIAGE)
        mock_gw.register("oncall_tool", "incident_attach_artifact", {"artifact": {"path": "t", "sha256": "x"}})
        mock_gw.register("oncall_tool", "incident_append_event", None, error="gateway timeout")

        graph = build_postmortem_draft_graph()

        with patch("app.graphs.postmortem_draft_graph.GatewayClient", return_value=mock_gw):
            result = _run(graph.ainvoke({
                "run_id": "gr_test_05",
                "agent_id": "sofiia",
                "workspace_id": "ws1",
                "user_id": "u1",
                "input": {"incident_id": "inc_20260223_1000_abc123"},
            }))

        assert result["graph_status"] == "succeeded"
        # followups may be 0 due to error, but graph still completed
        assert result["result"]["followups_count"] == 0

    def test_correlation_ids_present(self):
        from app.graphs.postmortem_draft_graph import build_postmortem_draft_graph

        mock_gw = MockGatewayClient()
        mock_gw.register("oncall_tool", "incident_get", _INCIDENT_WITH_TRIAGE)
        mock_gw.register("oncall_tool", "incident_attach_artifact", {"artifact": {}})
        mock_gw.register("oncall_tool", "incident_append_event", {"event": {}})

        graph = build_postmortem_draft_graph()

        with patch("app.graphs.postmortem_draft_graph.GatewayClient", return_value=mock_gw):
            _run(graph.ainvoke({
                "run_id": "gr_corr_01",
                "agent_id": "sofiia",
                "workspace_id": "ws1",
                "user_id": "u1",
                "input": {"incident_id": "inc_20260223_1000_abc123"},
            }))

        # All calls should have graph_run_id
        for call in mock_gw.calls:
            assert call["graph_run_id"] == "gr_corr_01"
