import datetime
from typing import Optional, Any
from pydantic import PositiveInt, validator
from pydantic.utils import GetterDict

from watcher.enums import (
    IntervalTypeEmployment,
    IntervalUnexpectedHolidays,
    IntervalWeekendsBehaviour,
    IntervalRotation,
)
from watcher.api.schemas.slot import SlotPutSchema, SlotListSchema

from .base import (
    BaseSchema,
    optional,
    name_type
)


class IntervalPutSchemaGetterDict(GetterDict):
    def get(self, key: str, default: Any = None) -> Any:
        if key == 'primary_rotation':
            return self._obj.primary_rotation or (
                self._obj.schedule.rotation is IntervalRotation.backup_is_next_primary
            )
        else:
            return super().get(key, default)


@optional('slots')
class IntervalBaseSchema(BaseSchema):
    name: Optional[name_type]
    schedule_id: PositiveInt
    order: PositiveInt
    duration: datetime.timedelta
    type_employment: IntervalTypeEmployment
    unexpected_holidays: IntervalUnexpectedHolidays
    weekend_behaviour: IntervalWeekendsBehaviour
    slots: list[SlotPutSchema] = []

    @validator('duration')
    def minimal_duration(cls, v):
        if v.total_seconds() < 600:
            raise ValueError('interval duration should be at least 10 minutes')
        return v


@optional(
    'id',
    'type_employment',
    'unexpected_holidays',
    'weekend_behaviour',
)
class IntervalPutSchema(IntervalBaseSchema):
    primary_rotation: Optional[bool] = False
    backup_takes_primary_shift: Optional[bool] = False
    id: PositiveInt

    class Config(BaseSchema.Config):
        getter_dict = IntervalPutSchemaGetterDict


class IntervalListSchema(IntervalPutSchema):
    revision_id: PositiveInt
    slots: Optional[list[SlotListSchema]]


class IntervalListPutSchema(BaseSchema):
    schedule_id: PositiveInt
    revision_id: Optional[PositiveInt]
    intervals: list[IntervalPutSchema]
    apply_datetime: Optional[datetime.datetime]
