from marshmallow import Schema, fields, validate

__all__ = [
    "FindNewTaskSchema",
    "StrictSchema",
    "TaskDetailsSchema",
    "UpdateTaskSchema",
    "with_schemas",
]


class with_schemas:
    """Decorator for deserializing input arguments and serializing returned
    value."""

    __slots__ = "input_schema", "output_schema"

    input_schema: Schema
    output_schema: Schema

    def __init__(self, input_schema: Schema, output_schema: Schema):
        self.input_schema = input_schema
        self.output_schema = output_schema

    def __call__(self, func):
        async def wrapped(s, **kwargs):
            dumped = self.input_schema().load(kwargs).data
            got = await func(s, **dumped)
            return self.output_schema().dump(got).data

        return wrapped


class StrictSchema(Schema):
    def __init__(self, *args, **kwargs):
        kwargs["strict"] = True
        super().__init__(*args, **kwargs)


class FindNewTaskSchema(StrictSchema):
    executor_id = fields.String(
        required=True,
        validate=validate.Length(min=1, error="Value should not be empty."),
    )


class TaskDetailsSchema(StrictSchema):
    timing_from = fields.DateTime(required=True)
    timing_to = fields.DateTime(required=True)
    id = fields.Integer(required=True)


class UpdateTaskSchema(StrictSchema):
    task_id = fields.Integer(required=True)
    executor_id = fields.String(
        required=True,
        validate=validate.Length(min=1, error="Value should not be empty."),
    )
