"""
Stub payment provider for local development and testing.

When PAYMENT_PROVIDER_STUB=true this provider is returned by
get_provider_for_merchant() and all payment operations succeed without
making any network calls.  It is completely invisible when the flag is false.
"""
from __future__ import annotations

import logging
from typing import Any, Dict, Optional
from uuid import uuid4

from src.core.providers.base import (
    BasePaymentProvider,
    ChargeResult,
    IframeConfig,
    ProviderConfig,
    TokenDetails,
)
from src.core.providers.registry import ProviderRegistry

logger = logging.getLogger(__name__)


@ProviderRegistry.register
class StubProvider(BasePaymentProvider):
    """
    In-memory stub that always succeeds without any network calls.

    Token details return a fake Visa card so downstream code that reads
    brand/last4/exp_month/exp_year gets sensible values.

    Charge results use a transaction id prefixed with 'stub_txn_' so that
    logs and DB records are clearly identifiable as synthetic.
    """

    slug = "stub"

    def get_iframe_config(
        self,
        config: ProviderConfig,
        amount: float = 0.0,
        currency: str = "USD",
    ) -> IframeConfig:
        return IframeConfig(
            sdk_url="",
            api_key="stub-api-key",
            merchant_id="stub-merchant",
            mode="test",
            extra={"stub": True, "amount": amount, "currency": currency},
        )

    async def get_token_details(self, config: ProviderConfig, token: str) -> TokenDetails:
        logger.info("StubProvider.get_token_details token=%s", token)
        return TokenDetails(
            provider_payment_method_id=token,
            provider="stub",
            brand="visa",
            last4="4242",
            exp_month="12",
            exp_year="2027",
        )

    async def create_payment_method(
        self,
        config: ProviderConfig,
        token: str,
        customer_context: Dict[str, Any],
    ) -> TokenDetails:
        logger.info("StubProvider.create_payment_method token=%s", token)
        return TokenDetails(
            provider_payment_method_id=token,
            provider="stub",
            brand="visa",
            last4="4242",
            exp_month="12",
            exp_year="2027",
        )

    async def submit_charge(
        self,
        config: ProviderConfig,
        amount: float,
        currency: str,
        payment_method_token: str,
        payment_method_type: str,
        capture: bool,
        idempotency_key: Optional[str],
        metadata: Optional[Dict[str, Any]],
    ) -> ChargeResult:
        txn_id = f"stub_txn_{uuid4().hex[:12]}"
        logger.info(
            "StubProvider.submit_charge txn_id=%s amount=%s currency=%s type=%s capture=%s",
            txn_id, amount, currency, payment_method_type, capture,
        )
        return ChargeResult(
            transaction_id=txn_id,
            status="succeeded",
            amount=amount,
            currency=currency,
            raw_response={
                "id": txn_id,
                "status": "approved",
                "amount": amount,
                "currency": currency,
                "stub": True,
            },
        )

    async def refund_charge(
        self,
        config: ProviderConfig,
        provider_transaction_id: str,
        amount: float,
        reason: Optional[str],
    ) -> ChargeResult:
        refund_id = f"stub_refund_{uuid4().hex[:12]}"
        logger.info(
            "StubProvider.refund_charge refund_id=%s original_txn=%s amount=%s",
            refund_id, provider_transaction_id, amount,
        )
        return ChargeResult(
            transaction_id=refund_id,
            status="succeeded",
            amount=amount,
            currency="USD",
            raw_response={
                "id": refund_id,
                "original_transaction_id": provider_transaction_id,
                "status": "approved",
                "amount": amount,
                "stub": True,
            },
        )

    def verify_webhook(
        self,
        config: ProviderConfig,
        headers: Dict[str, str],
        raw_body: bytes,
    ) -> bool:
        return True

    def parse_webhook_event(self, payload: Dict[str, Any]) -> Dict[str, Any]:
        return {
            "event_type": payload.get("event_type", "stub.event"),
            "transaction_id": payload.get("transaction_id", ""),
            "status": payload.get("status", "succeeded"),
            "amount": payload.get("amount", 0.0),
            "raw": payload,
        }
