from __future__ import annotations

from contextlib import asynccontextmanager
from unittest.mock import AsyncMock, MagicMock

import pytest


class _FakeMappings:
    def __init__(self, rows: list[dict]):
        self._rows = rows

    def all(self) -> list[dict]:
        return self._rows


class _FakeResult:
    def __init__(self, rows: list[dict]):
        self._rows = rows

    def mappings(self) -> _FakeMappings:
        return _FakeMappings(self._rows)


def _candidate_incident() -> dict:
    return {
        "incident_id": "INC-20260627-NODE110",
        "project_id": "awoooi",
        "status": "INVESTIGATING",
        "severity": "warning",
        "alertname": "NodeExporterDown",
        "alert_category": "infrastructure",
        "notification_type": "TYPE-3",
        "signals": [
            {
                "alert_name": "NodeExporterDown",
                "labels": {
                    "alertname": "NodeExporterDown",
                    "instance": "node-exporter-110",
                },
                "annotations": {},
            }
        ],
    }


@pytest.mark.asyncio
async def test_backfill_enqueues_catalog_matched_incident(monkeypatch: pytest.MonkeyPatch) -> None:
    from src.jobs import awooop_ansible_candidate_backfill_job as job

    fake_db = AsyncMock()
    fake_db.execute = AsyncMock(return_value=_FakeResult([_candidate_incident()]))

    @asynccontextmanager
    async def fake_db_context(project_id: str = "awoooi"):
        assert project_id == "awoooi"
        yield fake_db

    recorded: list[dict] = []

    async def fake_recorder(**kwargs):
        recorded.append(kwargs)
        return True

    async def fake_receipt_backfiller(**kwargs):
        assert kwargs["project_id"] == "awoooi"
        return {"written": 2, "error": None}

    monkeypatch.setattr(job, "get_db_context", fake_db_context)
    monkeypatch.setattr(job.settings, "ENABLE_AWOOOP_ANSIBLE_CANDIDATE_BACKFILL_WORKER", True)

    result = await job.enqueue_missing_ansible_candidates_once(
        project_id="awoooi",
        limit=5,
        window_hours=24,
        recorder=fake_recorder,
        receipt_backfiller=fake_receipt_backfiller,
    )

    assert result["queued"] == 1
    assert result["no_catalog_candidate"] == 0
    assert result["repair_receipts_backfilled"] == 2
    assert recorded[0]["decision_path"] == "repair_candidate_controlled_queue"
    assert recorded[0]["incident"]["incident_id"] == "INC-20260627-NODE110"


@pytest.mark.asyncio
async def test_backfill_skips_when_worker_disabled(monkeypatch: pytest.MonkeyPatch) -> None:
    from src.jobs import awooop_ansible_candidate_backfill_job as job

    monkeypatch.setattr(job.settings, "ENABLE_AWOOOP_ANSIBLE_CANDIDATE_BACKFILL_WORKER", False)

    result = await job.enqueue_missing_ansible_candidates_once()

    assert result["skipped"] is True
    assert result["queued"] == 0


def test_backfill_query_excludes_existing_ansible_candidate_rows() -> None:
    from src.jobs import awooop_ansible_candidate_backfill_job as job

    source = MagicMock(wraps=job._fetch_missing_candidate_incidents)
    query_source = job._fetch_missing_candidate_incidents.__code__.co_consts
    joined = "\n".join(str(item) for item in query_source)

    assert source is not None
    assert "NOT EXISTS" in joined
    assert "ansible_candidate_matched" in joined
    assert "resolved_at IS NULL" in joined
