from typing import Optional, Dict, Any
from sqlalchemy.orm import Session
from datetime import datetime, date, timedelta
from models import Appointment, Service
from repositories.base_repository import BaseRepository
from schemas.appointment import (
    AppointmentSchema,
    CreateAppointmentRequest,
    AppointmentResponseSchema
)


class AppointmentRepository(BaseRepository[AppointmentSchema, Appointment]):
    def __init__(self, db: Session):
        super().__init__(db, Appointment)

    def _to_entity(self, db_model: Appointment) -> Optional[AppointmentSchema]:
        return AppointmentSchema(
            id=db_model.id,
            appointment_no = db_model.appointment_no,
            company_id=db_model.company_id,
            name=db_model.name,
            phone=db_model.phone,
            start_datetime=db_model.start_datetime,
            end_datetime=db_model.end_datetime,
            summary=db_model.summary,
            service_id=db_model.service_id,
            status=db_model.status,
            created_at=db_model.created_at,
            updated_at=db_model.updated_at
        )

    def _to_db_model(self, entity: AppointmentSchema) -> Appointment:
        return Appointment(
            company_id=entity.company_id,
            appointment_no = entity.appointment_no,
            name=entity.name,
            phone=entity.phone,
            start_datetime=entity.start_datetime,
            end_datetime=entity.end_datetime,
            summary=entity.summary,
            service_id=entity.service_id,
            status=entity.status
        )

    def _to_response(self, db_model: Appointment, service_name: str) -> Optional[AppointmentResponseSchema]:
        return AppointmentResponseSchema(
            id=db_model.id,
            name=db_model.name,
            appointment_no = db_model.appointment_no,
            phone=db_model.phone,
            start_datetime=db_model.start_datetime,
            end_datetime=db_model.end_datetime,
            summary=db_model.summary,
            service_name=service_name,
            status=db_model.status
        )

    async def create_appointment(
        self,
        company_id: int,
        appointment_no: str,
        name: str,
        phone: str,
        start_datetime: datetime,
        end_datetime: datetime,
        service_id: int,
        summary: str | None = None
    ) -> AppointmentResponseSchema:
        appointment = Appointment(
            company_id=company_id,
            appointment_no=appointment_no,
            name=name,
            phone=phone,
            start_datetime=start_datetime,
            end_datetime=end_datetime,
            service_id=service_id,
            summary=summary
        )
        self.db.add(appointment)
        self.db.commit()
        self.db.refresh(appointment)

        # Get service name for response
        service = self.db.query(Service).filter(Service.id == service_id).first()
        return self._to_response(appointment, service.name if service else "Unknown Service")

    async def get_by_company(
        self,
        company_id: int,
        start: int = 0,
        limit: int = 10,
        appointment_date: date | None = None
    ) -> Dict[str, Any]:
        query = self.db.query(Appointment).filter(Appointment.company_id == company_id)
        
        if appointment_date:
            query = query.filter(
                Appointment.start_datetime >= appointment_date,
                Appointment.start_datetime < appointment_date + timedelta(days=1)
            )
        
        total = query.count()
        
        results = query.offset(start).limit(limit).all()
        
        formatted_appointments = []
        for appointment in results:
            service = self.db.query(Service).filter(Service.id == appointment.service_id).first()
            formatted_appointments.append({
                'id': appointment.id,
                'name': appointment.name,
                'phone': appointment.phone,
                'appointment_no': appointment.appointment_no,
                'start_datetime': appointment.start_datetime,
                'end_datetime': appointment.end_datetime,
                'summary': appointment.summary,
                'service_name': service.name if service else "Unknown Service",
                'status': appointment.status
            })
        
        return {
            "data": formatted_appointments,
            "total_count": total
        }

    async def cancel_appointment(self, appointment_id: int, company_id: int) -> bool:
        appointment = self.db.query(Appointment).filter(
            Appointment.id == appointment_id,
            Appointment.company_id == company_id
        ).first()

        if not appointment:
            return False

        appointment.status = 2  # 2 means cancelled
        self.db.commit()
        return True