import logging
import traceback
from typing import Any

from django.utils.translation import gettext_lazy as _
from drf_spectacular.utils import extend_schema, extend_schema_view
from rest_framework import status
from rest_framework.request import Request
from rest_framework.response import Response
from rest_framework.views import APIView

from engine.payments.docs.drf.views import DEPOSIT_SCHEMA, LIMITS_SCHEMA
from engine.payments.gateways import UnknownGatewayError
from engine.payments.models import Transaction
from engine.payments.serializers import (
    DepositSerializer,
    LimitsSerializer,
    TransactionProcessSerializer,
)
from engine.payments.utils.gateways import get_limits

logger = logging.getLogger(__name__)


@extend_schema_view(**DEPOSIT_SCHEMA)
class DepositView(APIView):
    __doc__ = _(
        "This class provides an API endpoint to handle deposit transactions.\n"
        "It supports the creation of a deposit transaction after validating the "
        "provided data. If the user is not authenticated, an appropriate response "
        "is returned. On successful validation and execution, a response "
        "with the transaction details is provided."
    )

    def post(
        self, request: Request, *args: list[Any], **kwargs: dict[Any, Any]
    ) -> Response:
        logger.debug(request.__dict__)
        serializer = DepositSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)

        if not request.user.is_authenticated:
            return Response(data=serializer.errors, status=status.HTTP_401_UNAUTHORIZED)

        # noinspection PyUnresolvedReferences
        transaction = Transaction.objects.create(
            balance=request.user.payments_balance,  # ty: ignore[unresolved-attribute]
            amount=serializer.validated_data["amount"],
            currency="EUR",
        )

        return Response(
            TransactionProcessSerializer(transaction).data,
            status=status.HTTP_303_SEE_OTHER,
        )


@extend_schema(exclude=True)
class CallbackAPIView(APIView):
    __doc__ = _(
        "Handles incoming callback requests to the API.\n"
        "This class processes and routes incoming HTTP POST requests to the appropriate "
        "pgateway handler based on the provided gateway parameter. It is designed to handle "
        "callback events coming from external systems and provide an appropriate HTTP response "
        "indicating success or failure."
    )

    def post(
        self, request: Request, *args: list[Any], **kwargs: dict[Any, Any]
    ) -> Response:
        try:
            transaction = Transaction.objects.get(uuid=str(kwargs.get("uuid")))
            if not transaction.gateway:
                raise UnknownGatewayError(
                    _(f"Transaction {transaction.uuid} has no gateway")
                )
            gateway_integration = transaction.gateway.get_integration_class_object(
                raise_exc=True
            )
            if not gateway_integration:
                raise UnknownGatewayError(
                    _(f"Gateway {transaction.gateway} has no integration")
                )
            gateway_integration.process_callback(request.data)
            return Response(status=status.HTTP_202_ACCEPTED)
        except Exception as e:
            return Response(
                status=status.HTTP_500_INTERNAL_SERVER_ERROR,
                data={"error": str(e), "detail": traceback.format_exc()},
            )


@extend_schema_view(**LIMITS_SCHEMA)
class LimitsAPIView(APIView):
    __doc__ = _(
        "This endpoint returns minimal and maximal allowed deposit amounts across available gateways."
    )

    def get(
        self, request: Request, *args: list[Any], **kwargs: dict[Any, Any]
    ) -> Response:
        min_amount, max_amount = get_limits()
        data = {"min_amount": min_amount, "max_amount": max_amount}
        return Response(LimitsSerializer(data).data, status=status.HTTP_200_OK)
