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

import typing

from hotpocket_soa.constants import BackendServiceErrorCode

if typing.TYPE_CHECKING:
    from django.core.exceptions import ValidationError


VALIDATION_CODE_INVALID = 'invalid'


def get_validation_error_data(validation_error: typing.Any) -> typing.Any:  # Heh
    if hasattr(validation_error, 'error_dict') is True:
        return {
            field: [
                get_validation_error_data(inner_error)
                for inner_error
                in inner_errors
            ]
            for field, inner_errors in validation_error.error_dict.items()
        }
    elif hasattr(validation_error, 'error_list') is True and len(validation_error.error_list) > 1:
        return [
            get_validation_error_data(inner_error)
            for inner_error
            in validation_error.error_list
        ]
    elif hasattr(validation_error, 'code') is True:
        return validation_error.code
    elif isinstance(validation_error, (tuple, list)) is True:
        return [
            get_validation_error_data(inner_error)
            for inner_error
            in validation_error
        ]
    elif isinstance(validation_error, dict) is True:
        return {
            field: [
                get_validation_error_data(inner_error)
                for inner_error
                in inner_errors
            ]
            for field, inner_errors in validation_error.items()
        }
    else:
        return VALIDATION_CODE_INVALID


class BackendServiceError(Exception):
    CODE = BackendServiceErrorCode.INTERNAL

    def __init__(self, message: str, *args):
        super().__init__(message, *args)
        self.message = message

        self.data: typing.Any = None
        if len(args) > 0:
            self.data = args[0]


class InternalError(BackendServiceError):
    pass


class NotFound(BackendServiceError):
    CODE = BackendServiceErrorCode.NOT_FOUND


class AccessDenied(BackendServiceError):
    CODE = BackendServiceErrorCode.ACCESS_DENIED


class Invalid(BackendServiceError):
    CODE = BackendServiceErrorCode.INVALID

    @classmethod
    def from_django_validation_error(cls: type[typing.Self],
                                     exception: ValidationError,
                                     message: str | None = None,
                                     ) -> typing.Self:
        data = get_validation_error_data(exception)

        result = cls(message or 'Invalid', data)
        result.__cause__ = exception

        return result
