import sys
from pathlib import Path

import asyncio

import pytest
from fastapi import HTTPException, status
from requests import RequestException

PROJECT_ROOT = Path(__file__).resolve().parents[1]
if str(PROJECT_ROOT) not in sys.path:
    sys.path.insert(0, str(PROJECT_ROOT))

from pydantic import ValidationError

from src.modules.pagamentos.mercadopago_service import (
    MercadoPagoService,
    MercadoPagoTransfer,
)


class _FakePaymentClient:
    def __init__(self, error: Exception) -> None:
        self._error = error

    def get(self, payment_id: int):  # pragma: no cover - behaviour tested via exception
        raise self._error


class _FakeSDK:
    def __init__(self, error: Exception) -> None:
        self._error = error

    def payment(self):  # pragma: no cover - simple passthrough
        return _FakePaymentClient(self._error)


def test_get_payment_translates_request_exception_to_bad_gateway():
    service = MercadoPagoService(access_token="token", public_key="public")
    service.sdk = _FakeSDK(RequestException("proxy error"))  # type: ignore[assignment]

    with pytest.raises(HTTPException) as error_info:
        asyncio.run(service.get_payment(123))

    assert error_info.value.status_code == status.HTTP_502_BAD_GATEWAY
    assert "Mercado Pago" in error_info.value.detail


def test_transfer_accepts_amount_or_percentage():
    transfer_amount = MercadoPagoTransfer(collector_id=123, amount=10.0)
    assert transfer_amount.amount == 10.0
    assert transfer_amount.percentage is None

    transfer_percentage = MercadoPagoTransfer(collector_id=123, percentage=25.0)
    assert transfer_percentage.percentage == 25.0
    assert transfer_percentage.amount is None


@pytest.mark.parametrize(
    "payload",
    [
        {"collector_id": 123},
        {"collector_id": 123, "amount": 10.0, "percentage": 10.0},
    ],
)
def test_transfer_requires_exclusive_amount_or_percentage(payload):
    with pytest.raises(ValidationError):
        MercadoPagoTransfer(**payload)


def test_prepare_preference_enforces_checkout_pro_payment_methods():
    service = MercadoPagoService(access_token="token", public_key="public")

    preference_payload = {
        "items": [
            {
                "id": "item-123",
                "title": "Produto teste",
                "quantity": 1,
                "unit_price": 100.0,
            }
        ],
        "payment_methods": {
            # Tenta bloquear cartão de crédito, mas deve ser ignorado
            "excluded_payment_types": [
                {"id": "ticket"},
                {"id": "credit_card"},
            ],
            # Tenta bloquear PIX, mas deve ser ignorado
            "excluded_payment_methods": [
                {"id": "pix"},
                {"id": "visa"},
            ],
            "installments": 12,
        },
    }

    prepared = service._prepare_preference_payload(preference_payload)

    excluded_types = {ptype["id"] for ptype in prepared["payment_methods"]["excluded_payment_types"]}
    excluded_methods = {pmethod["id"] for pmethod in prepared["payment_methods"]["excluded_payment_methods"]}

    assert "ticket" in excluded_types
    assert "credit_card" not in excluded_types
    assert "bank_transfer" not in excluded_types  # Mantém PIX habilitado
    assert "pix" not in excluded_methods
    assert prepared["payment_methods"]["installments"] == 1
