from typing import Dict, Any
from apps.appointments.models import Appointment
import logging


logger = logging.getLogger(__name__)


class AppointmentRepository:
    """
    Repository layer for Appointment DB operations.
    """

    @staticmethod
    def create_appointment(data: Dict[str, Any]) -> Appointment:
        """
        Create and return an Appointment instance.
        Expects `data` keys to match Appointment model fields.
        """
        return Appointment.objects.create(**data)

    @staticmethod
    def create_or_update_by_call_sid(data: Dict[str, Any]) -> Appointment:
        """
        One active appointment per Twilio Call SID.
        Rescheduling updates the same row.
        """

        lookup = {
            "twilio_call_sid": data["twilio_call_sid"],
            # "is_active": True,
        }

        defaults = {}

        for field in [
            "name",
            "scheduled_date",
            "appointment_phone",
            "offtime",
            "company",
            "call",
            "bot_type",
            "booking_type",
        ]:
            if field in data and data[field] is not None:
                defaults[field] = data[field]

        if not defaults:
            logger.warning(
                "Update called for appointment %s with no updatable fields",
                data["twilio_call_sid"]
            )

        missing_fields = [f for f in ["name", "scheduled_date"] if f not in defaults]
        if missing_fields:
            logger.info(
                "Partial update for appointment %s, missing fields: %s",
                data["twilio_call_sid"],
                missing_fields
            )

        appointment, created = Appointment.objects.update_or_create(
            **lookup,
            defaults=defaults,
        )

        return appointment

    @staticmethod
    def get_queryset():
        return Appointment.objects.exclude(call__isnull=True)

    @staticmethod
    def get_by_id(appointment_id: int) -> Appointment:
        """
        Retrieve an Appointment by its ID.
        Returns None if not found.
        """
        return AppointmentRepository.get_queryset().filter(
            id=appointment_id
        ).first()
