"""
drf-spectacular extension for attrs shape classes.
"""
import attr
from drf_spectacular.drainage import set_override
from drf_spectacular.extensions import OpenApiSerializerExtension
from drf_spectacular.plumbing import ResolvedComponent

import jsonschema_extractor


class AttrsExtension(OpenApiSerializerExtension):
    """
    Extension to support attrs classes in @extend_schema(request=..., response=...).
    """

    target_class = "attr.AttrsInstance"

    @classmethod
    def _matches(cls, target) -> bool:
        # attrs protocol isn't runtime-checkable, so use attr.has() instead.
        try:
            return attr.has(target)
        except TypeError:
            return False

    def get_name(self, auto_schema, direction):
        set_override(self.target, "suppress_collision_warning", True)
        return self.target.__name__

    def map_serializer(self, auto_schema, direction):
        schema = jsonschema_extractor.extract(self.target)

        # Register nested definitions as separate OpenAPI components.
        for def_name, def_schema in schema.pop("definitions", {}).items():
            component = ResolvedComponent(
                name=def_name,
                type=ResolvedComponent.SCHEMA,
                object=def_name,
                schema=def_schema,
            )
            auto_schema.registry.register_on_missing(component)

        return schema
