from mashumaro.meta.helpers import type_name


class MissingField(LookupError):
    def __init__(self, field_name, field_type, holder_class):
        self.field_name = field_name
        self.field_type = field_type
        self.holder_class = holder_class

    @property
    def field_type_name(self):
        return type_name(self.field_type)

    @property
    def holder_class_name(self):
        return type_name(self.holder_class)

    def __str__(self):
        return (
            f'Field "{self.field_name}" of type {self.field_type_name}'
            f" is missing in {self.holder_class_name} instance"
        )


class UnserializableDataError(TypeError):
    pass


class UnserializableField(UnserializableDataError):
    def __init__(self, field_name, field_type, holder_class, msg=None):
        self.field_name = field_name
        self.field_type = field_type
        self.holder_class = holder_class
        self.msg = msg

    @property
    def field_type_name(self):
        return type_name(self.field_type)

    @property
    def holder_class_name(self):
        return type_name(self.holder_class)

    def __str__(self):
        s = (
            f'Field "{self.field_name}" of type {self.field_type_name} '
            f"in {self.holder_class_name} is not serializable"
        )
        if self.msg:
            s += f": {self.msg}"
        return s


class InvalidFieldValue(ValueError):
    def __init__(
        self, field_name, field_type, field_value, holder_class, msg=None
    ):
        self.field_name = field_name
        self.field_type = field_type
        self.field_value = field_value
        self.holder_class = holder_class
        self.msg = msg

    @property
    def field_type_name(self):
        return type_name(self.field_type)

    @property
    def holder_class_name(self):
        return type_name(self.holder_class)

    def __str__(self):
        s = (
            f'Field "{self.field_name}" of type {self.field_type_name} '
            f"in {self.holder_class_name} has invalid value "
            f"{repr(self.field_value)}"
        )
        if self.msg:
            s += f": {self.msg}"
        return s


class BadHookSignature(TypeError):
    pass


class ThirdPartyModuleNotFoundError(ModuleNotFoundError):
    def __init__(self, module_name, field_name, holder_class):
        self.module_name = module_name
        self.field_name = field_name
        self.holder_class = holder_class

    @property
    def holder_class_name(self):
        return type_name(self.holder_class)

    def __str__(self):
        s = (
            f'Install "{self.module_name}" to use it as the serialization '
            f'method for the field "{self.field_name}" '
            f"in {self.holder_class_name}"
        )
        return s
