"""
Tests for the Manifold outcome-compatibility guard.

Regression: a Polymarket *nomination* question must not match a Manifold
*conditional* question ("If X is the nominee, will he win?") even at Jaccard=1.0.
"""
import asyncio

import pytest

from bot.data.manifold import (
    ManifoldClient,
    _classify_outcome,
    _is_conditional,
)


# ── _is_conditional ────────────────────────────────────────────────────────────
def test_is_conditional_prefixes():
    assert _is_conditional("If Graham Platner is the nominee, will he win?")
    assert _is_conditional("Conditional on a recession, will rates fall?")
    assert _is_conditional("Assuming Trump runs, will he win?")
    assert _is_conditional("Given that X happens, will Y?")


def test_is_conditional_midsentence_clause():
    assert _is_conditional("Will Biden, if he is nominated, win the election?")


def test_is_not_conditional():
    assert not _is_conditional("Will Graham Platner be the Democratic nominee?")
    assert not _is_conditional("Will the GOP win the Senate?")
    # "if" without a closing comma clause is not flagged
    assert not _is_conditional("What happens if everything goes right")


# ── _classify_outcome ───────────────────────────────────────────────────────────
def test_classify_nomination():
    assert _classify_outcome("Will X be the Democratic nominee for Senate?") == "nomination"
    assert _classify_outcome("Will X be nominated?") == "nomination"
    # "primary nominee" → nomination (checked before primary)
    assert _classify_outcome("Will X be the primary nominee?") == "nomination"


def test_classify_primary_win():
    assert _classify_outcome("Will X win the primary?") == "primary_win"
    assert _classify_outcome("Will X advance in the first round?") == "primary_win"


def test_classify_general_win():
    assert _classify_outcome("Will X win the election?") == "general_win"
    assert _classify_outcome("Will X win the seat?") == "general_win"
    assert _classify_outcome("Will X win the general election?") == "general_win"


def test_classify_conditional():
    assert _classify_outcome("If X is the nominee, will he win?") == "conditional"
    assert _classify_outcome("Assuming a runoff, who wins?") == "conditional"


def test_classify_other():
    assert _classify_outcome("Will it rain tomorrow?") == "other"


# ── End-to-end get_match with a stubbed Manifold API ────────────────────────────
class _StubResponse:
    def __init__(self, payload):
        self._payload = payload

    def raise_for_status(self):
        pass

    def json(self):
        return self._payload


class _StubHTTP:
    def __init__(self, payload):
        self._payload = payload

    async def get(self, *args, **kwargs):
        return _StubResponse(self._payload)

    async def aclose(self):
        pass


async def _match(poly, mfld_market):
    client = ManifoldClient()
    client._client = _StubHTTP([mfld_market])
    try:
        return await client.get_match(poly)
    finally:
        await client.close()


def test_graham_platner_conditional_rejected():
    """Poly nomination vs Manifold conditional → rejected (Task 4.1)."""
    poly = ("Will Graham Platner be the Democratic nominee for Senate "
            "in Maine in 2026?")
    mfld_market = {
        "outcomeType": "BINARY",
        "probability": 0.55,
        "question": ("If Graham Platner is the Democratic nominee for Senate "
                     "in Maine, will he win the general election?"),
        "id": "abc123",
        "slug": "graham-platner-win",
        "creatorUsername": "someone",
    }
    result = asyncio.run(_match(poly, mfld_market))

    assert result.status == "rejected"
    assert result.match_reason is not None
    assert ("conditional" in result.match_reason
            or "outcome_mismatch" in result.match_reason)
    # outcome types are classified and available for persistence
    assert result.poly_outcome_type == "nomination"
    assert result.mfld_outcome_type == "conditional"


def test_outcome_mismatch_nomination_vs_general_rejected():
    """Poly nomination vs Manifold general_win (non-conditional) → rejected."""
    poly = "Will Jane Doe be the Republican nominee for Governor?"
    mfld_market = {
        "outcomeType": "BINARY",
        "probability": 0.4,
        "question": "Will Jane Doe win the election for Governor?",
        "id": "x", "slug": "jane-doe", "creatorUsername": "u",
    }
    result = asyncio.run(_match(poly, mfld_market))

    assert result.status == "rejected"
    assert "outcome_mismatch" in result.match_reason
    assert result.poly_outcome_type == "nomination"
    assert result.mfld_outcome_type == "general_win"


def test_matching_nomination_accepted():
    """Poly nomination vs Manifold nomination (same outcome) → accepted."""
    poly = "Will Graham Platner be the Democratic nominee for Senate in Maine?"
    mfld_market = {
        "outcomeType": "BINARY",
        "probability": 0.62,
        "question": "Will Graham Platner be the Democratic Senate nominee in Maine?",
        "id": "ok", "slug": "platner-nominee", "creatorUsername": "u",
    }
    result = asyncio.run(_match(poly, mfld_market))

    assert result.status == "accepted"
    assert result.poly_outcome_type == "nomination"
    assert result.mfld_outcome_type == "nomination"
    assert result.prob_final == pytest.approx(0.62)
