import json
import logging

from aiohttp.web import Response, middleware
from marshmallow import ValidationError

from maps_adv.geosmb.booking_yang.proto.errors_pb2 import Error
from maps_adv.geosmb.booking_yang.server.lib.domains.exceptions import (
    InsufficientTimeToConfirm,
    OrgNotFound,
    OrgWithoutPhone,
)

__all__ = ["handle_validation_errors", "handle_domain_errors"]


@middleware
async def handle_validation_errors(request, handler):
    try:
        return await handler(request)
    except ValidationError as exc:
        error = Error(
            code=Error.DATA_VALIDATION_ERROR, description=json.dumps(exc.messages)
        )
        return Response(status=400, body=error.SerializeToString())


@middleware
async def handle_domain_errors(request, handler):
    try:
        return await handler(request)

    except OrgNotFound as exc:
        logging.getLogger(__name__).exception("Org not found", exc_info=exc)
        return Response(
            status=404,
            body=Error(
                code=Error.ORG_NOT_FOUND, description=str(exc)
            ).SerializeToString(),
        )

    except OrgWithoutPhone as exc:
        logging.getLogger(__name__).exception("Org without phone", exc_info=exc)
        return Response(
            status=404,
            body=Error(
                code=Error.ORG_WITHOUT_PHONE, description=str(exc)
            ).SerializeToString(),
        )

    except InsufficientTimeToConfirm:
        return Response(
            status=409,
            body=Error(code=Error.INSUFFICIENT_TIME_TO_CONFIRM).SerializeToString(),
        )
