from datetime import date
from typing import Optional, List

from staff.workspace_management import entities, models


class Repository(entities.Repository):
    @staticmethod
    def _entity_to_model(share_pie: entities.RoomSharePie) -> models.RoomSharePie:
        return models.RoomSharePie(
            id=share_pie.room_share_pie_id,
            room_id=share_pie.room_id,
            room_area=share_pie.room_area,
            from_date=share_pie.from_date,
            to_date=share_pie.to_date,
            author_id=share_pie.author_id,
        )

    @staticmethod
    def _share_to_model(share: entities.Share, share_pie: entities.RoomSharePie) -> models.Share:
        return models.Share(
            room_share_pie_id=share_pie.room_share_pie_id,
            business_unit_id=share.business_unit_id,
            share_value=share.share_value,
        )

    @staticmethod
    def _model_to_entity(share_pie_model: models.RoomSharePie) -> entities.RoomSharePie:
        shares = [
            entities.Share(share_value=share.share_value, business_unit_id=share.business_unit_id)
            for share in share_pie_model.shares.all()
        ]

        return entities.RoomSharePie(
            room_share_pie_id=share_pie_model.id,
            room_id=share_pie_model.room_id,
            author_id=share_pie_model.author_id,
            from_date=share_pie_model.from_date,
            to_date=share_pie_model.to_date,
            room_area=share_pie_model.room_area,
            shares=shares,
        )

    def last_share_pie_for_room(self, room_id: int) -> Optional[entities.RoomSharePie]:
        share_pie_model = models.RoomSharePie.objects.filter(room_id=room_id).order_by('-created_at').first()
        if not share_pie_model:
            return None

        return Repository._model_to_entity(share_pie_model)

    def share_pie_for_room_and_date(self, room_id: int, current_date: date) -> Optional[entities.RoomSharePie]:
        share_pie_model = (
            models.RoomSharePie.objects
            .filter(room_id=room_id, from_date__lte=current_date, to_date__gt=current_date)
            .first()
        )

        if not share_pie_model:
            return None

        return Repository._model_to_entity(share_pie_model)

    def share_pies_for_rooms_and_date(self, room_ids: List[int], current_date: date) -> List[entities.RoomSharePie]:
        qs = (
            models.RoomSharePie.objects
            .filter(room_id__in=room_ids, from_date__lte=current_date, to_date__gt=current_date)
        )

        return [Repository._model_to_entity(row) for row in qs]

    def save_share_pie(self, share_pie: entities.RoomSharePie) -> None:
        models.RoomSharePie.objects.filter(id=share_pie.room_share_pie_id).delete()
        Repository._entity_to_model(share_pie).save()
        share_models = [Repository._share_to_model(share, share_pie) for share in share_pie.shares]
        models.Share.objects.bulk_create(share_models)
