# -*- coding: utf-8 -*-
from __future__ import annotations

import functools
import typing

from bthlabs_jsonrpc_core.exceptions import BaseJSONRPCError
from bthlabs_jsonrpc_django import (
    DjangoExecutor,
    DjangoJSONRPCSerializer,
    JSONRPCView as BaseJSONRPCView,
)
import uuid6

from hotpocket_soa.exceptions.frontend import SOAError


class SOAJSONRPCError(BaseJSONRPCError):
    ERROR_CODE = -32000
    ERROR_MESSAGE = 'SOA Error'

    def to_rpc(self) -> dict:
        exception = typing.cast(SOAError, self.data)

        code = (
            exception.code
            if exception.code is not None
            else self.ERROR_CODE
        )

        return {
            'code': code,
            'message': exception.message or self.ERROR_MESSAGE,
            'data': exception.data,
        }


class JSONRPCSerializer(DjangoJSONRPCSerializer):
    STRING_COERCIBLE_TYPES: typing.Any = (
        *DjangoJSONRPCSerializer.STRING_COERCIBLE_TYPES,
        uuid6.UUID,
    )


class Executor(DjangoExecutor):
    serializer = JSONRPCSerializer


class JSONRPCView(BaseJSONRPCView):
    executor = Executor


def wrap_soa_errors(func: typing.Callable) -> typing.Callable:
    @functools.wraps(func)
    def decorator(*args, **kwargs):
        try:
            return func(*args, **kwargs)
        except SOAError as exception:
            raise SOAJSONRPCError(exception)

    return decorator
