from enum import Enum
from typing import Dict, Optional

import yaml
from dihttpmessageprocessor import AutoMappedDiRouterProcessorBuilder
from messageprocessor import MessageProcessor
from simplehttprouter import Route
from yaml.representer import BaseRepresenter

from ..interactor.dto import AutoOpenApiYamlBuilderRequest
from ..model import BaseModel, ServerModel
from ..model_builder import OpenApiModelBuilder


def represent_base_model(rep: BaseRepresenter, data: BaseModel):
    if isinstance(data, BaseModel):
        data = data.get_model_data()
    return rep.represent_mapping('tag:yaml.org,2002:map', data)


def represent_enum(rep: BaseRepresenter, data: Enum):
    return rep.represent_scalar('tag:yaml.org,2002:str', data.value)


yaml.add_multi_representer(BaseModel, represent_base_model)
yaml.add_multi_representer(Enum, represent_enum)


class AutoOpenApiYamlBuilderInteractor:
    def __init__(self, routes: Optional[Dict[Route, MessageProcessor]] = None):
        self.routes = routes
        self.builder = OpenApiModelBuilder()


    def execute(self, request: AutoOpenApiYamlBuilderRequest) -> str:
        if request.host is not None:
            self.builder.model.add_server(
                server=ServerModel(
                    url=request.host,
                )
            )

        if self.routes is not None:
            for route, processor in self.routes.items():
                self.builder.add_processor_path(
                    route=route,
                    processor=processor,
                )

        return yaml.dump(
            self.builder.model,
            sort_keys=False,
        )
