"""
Payrix payment provider client.

Delegates to the existing payrix utility functions so that all Payrix-
specific logic stays in its current home and is not duplicated here.
This wrapper simply satisfies the PaymentProviderClient interface.
"""
from __future__ import annotations

import logging
from typing import Any, Dict, Optional

from sqlalchemy.orm import Session

from src.core.payment_provider.base import PaymentProviderClient

logger = logging.getLogger(__name__)


class PayrixProviderClient(PaymentProviderClient):
    """
    Production payment provider client backed by Payrix.

    Because the existing payrix utilities require an SQLAlchemy session and
    merchant / customer context that is not part of the abstract interface,
    this client stores a reference to those objects at construction time.
    Callers that need to pass a session should build the client themselves;
    the factory `get_provider_client()` in __init__.py constructs a
    session-less instance suitable for submit_charge() which does not need
    a session.
    """

    def __init__(self, session: Optional[Session] = None) -> None:
        self._session = session

    async def get_token_details(self, token: str, merchant_id: int = 0) -> Dict[str, Any]:
        """
        Delegate to `get_payment_token_details()` from payment_methods/utils/payrix.

        A session must have been supplied at construction time; if not,
        raises RuntimeError.
        """
        from src.apps.payment_methods.utils.payrix import get_payment_token_details

        if self._session is None:
            raise RuntimeError(
                "PayrixProviderClient.get_token_details() requires a database "
                "session.  Pass session= when constructing the client."
            )

        # get_payment_token_details signature:
        # (session, *, token, merchant_id, customer_id=None) -> Dict
        result: Dict[str, Any] = await get_payment_token_details(
            self._session,
            token=token,
            merchant_id=merchant_id,
        )
        return result

    async def submit_charge(
        self,
        *,
        amount: float,
        currency: str,
        customer_id: int,
        merchant_id: int,
        token: str,
        payment_method_type: str = "card",
        capture: bool = True,
        **kwargs: Any,
    ) -> Dict[str, Any]:
        """
        Delegate to `submit_payrix_charge()` from _lib/utils/payrix_transactions.
        """
        from src.apps._lib.utils.payrix_transactions import submit_payrix_charge

        result: Dict[str, Any] = await submit_payrix_charge(
            amount=amount,
            currency=currency,
            customer_id=customer_id,
            payrix_token=token,
            payment_method_type=payment_method_type,
            merchant_id=merchant_id,
            capture=capture,
        )
        return result
