from __future__ import annotations

import logging
from typing import Any

from spherepay_mcp.adapters.reliability import IdempotencyStrategy
from spherepay_mcp.domain.value_objects import ApiError, ErrorCategory
from spherepay_mcp.ports.spherepay_gateway import SpherePayGateway

logger = logging.getLogger(__name__)


class TransferWorkflowService:
    """Orchestrates transfer creation with idempotency."""

    def __init__(self, gateway: SpherePayGateway, idempotency: IdempotencyStrategy | None = None):
        self._gw = gateway
        self._idempotency = idempotency or IdempotencyStrategy()

    async def execute_transfer(
        self,
        source_id: str,
        destination_id: str,
        amount: str,
        source_currency: str,
        destination_currency: str,
        source_network: str,
        destination_network: str,
        customer_id: str | None = None,
    ) -> dict[str, Any]:
        """Execute a money transfer with automatic idempotency key generation.

        The idempotency key is derived from the transfer parameters to prevent
        duplicate transfers on retry.
        """
        payload: dict[str, Any] = {
            "sourceId": source_id,
            "destinationId": destination_id,
            "amount": amount,
            "sourceCurrency": source_currency,
            "destinationCurrency": destination_currency,
            "sourceNetwork": source_network,
            "destinationNetwork": destination_network,
        }
        if customer_id:
            payload["customerId"] = customer_id

        idempotency_key = self._idempotency.generate_key("create_transfer", payload)

        try:
            result = await self._gw.create_transfer(payload, idempotency_key=idempotency_key)
        except ApiError as e:
            if e.category == ErrorCategory.CONFLICT:
                logger.info("Idempotency conflict for transfer, returning existing resource")
                return {
                    "data": e.details or {},
                    "idempotency_note": "Transfer already exists with these parameters (idempotency conflict). Returning existing transfer.",
                }
            raise

        return {
            "data": result.get("data", result),
            "idempotency_key": idempotency_key,
            "next_steps": [
                "Use get_transfer to check transfer status",
                "Transfer may take time to process depending on network",
            ],
        }
