"""
Checkout API resource.

Endpoints:
    POST /v1/checkout/sessions
    GET  /v1/checkout/sessions/:id
    GET  /v1/checkout/sessions
    GET  /v1/checkout/sessions/search
    POST /v1/checkout/sessions/:id/expire
    POST /v1/checkout/sessions/:id/refund
"""

from typing import Any, Dict, List, Optional

from .session import WaveSession


class CheckoutAPI:
    """
    Interact with the Wave Checkout API.

    Create payment sessions, retrieve session status, search by client
    reference, expire open sessions, and refund completed payments.
    """

    def __init__(self, session: WaveSession):
        self._session = session

    def create_session(
        self,
        amount: str,
        currency: str,
        success_url: str,
        error_url: str,
        client_reference: Optional[str] = None,
        restrict_payer_mobile: Optional[str] = None,
        aggregated_merchant_id: Optional[str] = None,
    ) -> Dict[str, Any]:
        """
        Create a new Checkout Session.

        After creation, redirect the user to the ``wave_launch_url``
        from the response to initiate payment in the Wave app.

        Args:
            amount: Total amount to collect (string, e.g. "1000").
            currency: ISO 4217 currency code (e.g. "XOF").
            success_url: HTTPS URL to redirect to on payment success.
            error_url: HTTPS URL to redirect to on payment error.
            client_reference: Optional unique string for your system's correlation.
            restrict_payer_mobile: If set, only this phone number can pay.
            aggregated_merchant_id: Aggregated merchant ID (aggregators only).

        Returns:
            Checkout Session object::

                {
                    "id": "cos-18qq25rgr100a",
                    "amount": "1000",
                    "checkout_status": "open",
                    "wave_launch_url": "https://pay.wave.com/c/cos-...",
                    ...
                }

        Example::

            session = client.checkout.create_session(
                amount="5000",
                currency="XOF",
                success_url="https://myapp.com/success",
                error_url="https://myapp.com/error",
                client_reference="order-42",
            )
            # Redirect user to session["wave_launch_url"]
        """
        payload: Dict[str, Any] = {
            "amount": amount,
            "currency": currency,
            "success_url": success_url,
            "error_url": error_url,
        }
        if client_reference:
            payload["client_reference"] = client_reference
        if restrict_payer_mobile:
            payload["restrict_payer_mobile"] = restrict_payer_mobile
        if aggregated_merchant_id:
            payload["aggregated_merchant_id"] = aggregated_merchant_id

        return self._session.post("/v1/checkout/sessions", json=payload)

    def get_session(self, session_id: str) -> Dict[str, Any]:
        """
        Retrieve a Checkout Session by its ID.

        Args:
            session_id: Checkout session ID (starts with 'cos-').

        Returns:
            Checkout Session object.

        Raises:
            WaveNotFoundError: If the session does not exist.

        Example::

            session = client.checkout.get_session("cos-18qq25rgr100a")
            print(session["checkout_status"])  # "complete"
        """
        return self._session.get(f"/v1/checkout/sessions/{session_id}")

    def get_session_by_transaction(self, transaction_id: str) -> Dict[str, Any]:
        """
        Retrieve a Checkout Session by Wave transaction ID.

        Args:
            transaction_id: Wave transaction ID (starts with 'T_').

        Returns:
            Checkout Session object.

        Raises:
            WaveNotFoundError: If no session matches the transaction ID.

        Example::

            session = client.checkout.get_session_by_transaction("TCN4Y4ZC3FM")
        """
        return self._session.get("/v1/checkout/sessions", params={"transaction_id": transaction_id})

    def search_sessions(self, client_reference: str) -> List[Dict[str, Any]]:
        """
        Search Checkout Sessions by client reference.

        Args:
            client_reference: Your unique reference string.

        Returns:
            List of matching Checkout Session objects.

        Example::

            results = client.checkout.search_sessions("order-42")
            for session in results:
                print(session["id"], session["payment_status"])
        """
        response = self._session.get(
            "/v1/checkout/sessions/search",
            params={"client_reference": client_reference},
        )
        return response.get("result", [])

    def expire_session(self, session_id: str) -> None:
        """
        Expire an open Checkout Session immediately.

        Prevents any further payment attempts on this session.

        Args:
            session_id: Checkout session ID (starts with 'cos-').

        Returns:
            None on success.

        Raises:
            WaveNotFoundError: If the session does not exist.
            WaveIdempotencyError: If the session is already completed or expired.

        Example::

            client.checkout.expire_session("cos-18qq25rgr100a")
        """
        return self._session.post(f"/v1/checkout/sessions/{session_id}/expire")

    def refund_session(self, session_id: str) -> None:
        """
        Refund the payment associated with a completed Checkout Session.

        This operation is idempotent — calling it twice will not create
        a duplicate refund.

        Args:
            session_id: Checkout session ID (starts with 'cos-').

        Returns:
            None on success.

        Raises:
            WaveNotFoundError: If the session does not exist.
            WaveAPIError: If the refund fails (e.g., insufficient funds).

        Example::

            client.checkout.refund_session("cos-18qq25rgr100a")
        """
        return self._session.post(f"/v1/checkout/sessions/{session_id}/refund")
