from typing import Optional, List
from sqlalchemy.orm import Session
from models import WeeklySchedule
from repositories.base_repository import BaseRepository
from schemas.schedule import (
    WeeklyScheduleSchema,
    ScheduleItem,
    CreateWeeklyScheduleSchema,
    ScheduleResponseSchema
)
from utils.constants import WeeklyScheduleStatus
from datetime import datetime, timezone


class WeeklyScheduleRepository(BaseRepository[WeeklyScheduleSchema, WeeklySchedule]):
    def __init__(self, db: Session):
        super().__init__(db, WeeklySchedule)

    def _to_entity(self, db_model: Optional[WeeklySchedule]) -> Optional[WeeklyScheduleSchema]:
        if not db_model:
            return None
        return WeeklyScheduleSchema(
            id=db_model.id,
            company_id=db_model.company_id,
            day_of_week=db_model.day_of_week,
            start_time=db_model.start_time,
            end_time=db_model.end_time,
            is_day_off=db_model.is_day_off,
            created_at=db_model.created_at.isoformat(),
            updated_at=db_model.updated_at.isoformat()
        )

    def _to_response(self, db_model: Optional[WeeklySchedule]) -> Optional[ScheduleResponseSchema]:
        if not db_model:
            return None
        return ScheduleResponseSchema(
            id=db_model.id,
            day_of_week=db_model.day_of_week,
            start_time=db_model.start_time,
            end_time=db_model.end_time,
            is_day_off=db_model.is_day_off
        )

    def _to_db_model(self, entity: WeeklyScheduleSchema) -> WeeklySchedule:
        return WeeklySchedule(
            company_id=entity.company_id,
            day_of_week=entity.day_of_week,
            start_time=entity.start_time,
            end_time=entity.end_time,
            is_day_off=entity.is_day_off
        )

    async def create_schedule(self, company_id: int, day_of_week: int, start_time: str, end_time: str, is_day_off: int = WeeklyScheduleStatus.NOT_OFF) -> ScheduleResponseSchema:
        schedule = CreateWeeklyScheduleSchema(
            company_id=company_id,
            day_of_week=day_of_week,
            start_time=start_time,
            end_time=end_time,
            is_day_off=is_day_off
        )
        db_model = WeeklySchedule(
            company_id=schedule.company_id,
            day_of_week=schedule.day_of_week,
            start_time=schedule.start_time,
            end_time=schedule.end_time,
            is_day_off=schedule.is_day_off
        )
        self.db.add(db_model)
        self.db.commit()
        self.db.refresh(db_model)
        return self._to_response(db_model)

    async def update_schedule(self, schedule_id: int, start_time: str, end_time: str, is_day_off: int) -> ScheduleResponseSchema:
        schedule = self.db.query(WeeklySchedule).filter(WeeklySchedule.id == schedule_id).first()
        if not schedule:
            return None

        schedule.start_time = start_time
        schedule.end_time = end_time
        schedule.is_day_off = is_day_off
        schedule.updated_at = datetime.now(timezone.utc)

        self.db.commit()
        self.db.refresh(schedule)
        return self._to_response(schedule)

    async def create_schedules(self, company_id: int, schedules: List[ScheduleItem]) -> List[ScheduleResponseSchema]:
        created_schedules = []
        for schedule in schedules:
            if schedule.is_day_off:
                start_time = "00:00:00"
                end_time = "00:00:00"
            else:
                if not schedule.start_time or not schedule.end_time:
                    continue
                start_time = schedule.start_time.strftime("%H:%M:%S")
                end_time = schedule.end_time.strftime("%H:%M:%S")

            existing = await self.get_by_company_and_day(company_id, schedule.day_of_week)
            if existing:
                updated_schedule = await self.update_schedule(
                    schedule_id=existing.id,
                    start_time=start_time,
                    end_time=end_time,
                    is_day_off=1 if schedule.is_day_off else 0
                )
                created_schedules.append(updated_schedule)
            else:
                new_schedule = await self.create_schedule(
                    company_id=company_id,
                    day_of_week=schedule.day_of_week,
                    start_time=start_time,
                    end_time=end_time,
                    is_day_off=1 if schedule.is_day_off else 0
                )
                created_schedules.append(new_schedule)

        return created_schedules

    async def get_by_company(self, company_id: int) -> List[ScheduleResponseSchema]:
        schedules = self.db.query(WeeklySchedule).filter(WeeklySchedule.company_id == company_id).all()
        return [self._to_response(schedule) for schedule in schedules]

    async def get_by_company_and_day(self, company_id: int, day_of_week: int) -> Optional[ScheduleResponseSchema]:
        schedule = self.db.query(WeeklySchedule).filter(
            WeeklySchedule.company_id == company_id,
            WeeklySchedule.day_of_week == day_of_week
        ).first()
        return self._to_response(schedule) if schedule else None 