"""Calendar selector layer — all reads go through here."""

from __future__ import annotations

from datetime import datetime

from django.db.models import Q, QuerySet

from simorgh.apps.calendar.models import CalendarEvent, EventAttendee


def get_events_for_range(
    tenant_id: int,
    user_id: int,
    from_dt: datetime,
    to_dt: datetime,
    owner_id: int | None = None,
    manage_others: bool = False,
) -> QuerySet[CalendarEvent]:
    """Return events overlapping [from_dt, to_dt) for the given tenant."""
    qs = CalendarEvent.objects.filter(
        tenant_id=tenant_id,
        start_dt__lt=to_dt,
        end_dt__gt=from_dt,
    )
    if not manage_others:
        qs = qs.filter(
            Q(owner_id=user_id) | Q(attendees__user_id=user_id)
        ).distinct()
    if owner_id is not None:
        qs = qs.filter(owner_id=owner_id)
    return qs.select_related("owner")


def get_event_by_public_id(tenant_id: int, public_id: str) -> CalendarEvent | None:
    """Return a CalendarEvent by its UUID public_id within a tenant, or None."""
    try:
        return CalendarEvent.objects.get(tenant_id=tenant_id, public_id=public_id)
    except (CalendarEvent.DoesNotExist, Exception):
        return None


def get_linked_events(
    tenant_id: int,
    user_id: int,
    linked_type: str,
    linked_id: str,
) -> QuerySet[CalendarEvent]:
    """Return events linked to a specific domain object."""
    from django.contrib.contenttypes.models import ContentType

    type_map: dict[str, tuple[str, str]] = {
        "lead": ("crm", "lead"),
        "opportunity": ("crm", "opportunity"),
    }
    if linked_type not in type_map:
        return CalendarEvent.objects.none()

    app_label, model_name = type_map[linked_type]
    try:
        ct = ContentType.objects.get(app_label=app_label, model=model_name)
    except ContentType.DoesNotExist:
        return CalendarEvent.objects.none()

    return CalendarEvent.objects.filter(
        tenant_id=tenant_id,
        linked_objects__content_type=ct,
        linked_objects__object_id=linked_id,
    ).filter(
        Q(owner_id=user_id) | Q(attendees__user_id=user_id)
    ).distinct()


def get_attendees(event_id: int) -> QuerySet[EventAttendee]:
    """Return all attendees for an event."""
    return EventAttendee.objects.filter(event_id=event_id).select_related("user")
