"""Calendar service layer — all mutations go through here."""

from __future__ import annotations

from datetime import datetime

from django.core.exceptions import ValidationError

from simorgh.apps.calendar.models import AttendeeStatus, CalendarEvent, EventAttendee


# ---------------------------------------------------------------------------
# Event CRUD
# ---------------------------------------------------------------------------

def create_event(
    *,
    tenant_id: int,
    organization_node_id: int,
    owner_id: int,
    title: str,
    start_dt: datetime,
    end_dt: datetime,
    all_day: bool = False,
    description: str = "",
    location: str = "",
    color: str = "",
    is_recurring: bool = False,
) -> CalendarEvent:
    """Create and persist a new CalendarEvent.

    Raises ValidationError if end_dt is not after start_dt (for non-all-day events).
    """
    if not all_day and end_dt <= start_dt:
        raise ValidationError("end_dt must be after start_dt")

    event = CalendarEvent.objects.create(
        tenant_id=tenant_id,
        organization_node_id=organization_node_id,
        owner_id=owner_id,
        title=title,
        start_dt=start_dt,
        end_dt=end_dt,
        all_day=all_day,
        description=description,
        location=location,
        color=color,
        is_recurring=is_recurring,
    )
    _fire("calendar.event.created", {
        "event_id": str(event.public_id),
        "tenant_id": event.tenant_id,
        "owner_id": event.owner_id,
    })
    return event


def update_event(event: CalendarEvent, **kwargs) -> CalendarEvent:
    """Update fields on an existing CalendarEvent."""
    start_dt = kwargs.get("start_dt", event.start_dt)
    end_dt = kwargs.get("end_dt", event.end_dt)
    all_day = kwargs.get("all_day", event.all_day)
    if not all_day and end_dt <= start_dt:
        raise ValidationError("end_dt must be after start_dt")

    for field, value in kwargs.items():
        setattr(event, field, value)
    event.save()
    _fire("calendar.event.updated", {
        "event_id": str(event.public_id),
        "tenant_id": event.tenant_id,
    })
    return event


def delete_event(event: CalendarEvent) -> None:
    """Delete a CalendarEvent permanently."""
    payload = {
        "event_id": str(event.public_id),
        "tenant_id": event.tenant_id,
    }
    event.delete()
    _fire("calendar.event.deleted", payload)


# ---------------------------------------------------------------------------
# Attendees
# ---------------------------------------------------------------------------

def add_attendee(
    event: CalendarEvent,
    *,
    user_id: int | None = None,
    external_email: str = "",
    status: str = AttendeeStatus.PENDING,
) -> EventAttendee:
    """Add an attendee to a CalendarEvent (idempotent for existing user attendees)."""
    if user_id:
        attendee, _ = EventAttendee.objects.get_or_create(
            event=event,
            user_id=user_id,
            defaults={"external_email": "", "status": status},
        )
    else:
        attendee = EventAttendee.objects.create(
            event=event,
            user=None,
            external_email=external_email,
            status=status,
        )
    return attendee


def remove_attendee(event: CalendarEvent, user_id: int) -> None:
    """Remove a user attendee from a CalendarEvent."""
    EventAttendee.objects.filter(event=event, user_id=user_id).delete()


def respond_attendee(event: CalendarEvent, user_id: int, status: str) -> EventAttendee | None:
    """Update an attendee's response status."""
    try:
        attendee = EventAttendee.objects.get(event=event, user_id=user_id)
    except EventAttendee.DoesNotExist:
        return None
    attendee.status = status
    attendee.save(update_fields=["status", "updated_at"])
    return attendee


# ---------------------------------------------------------------------------
# Internal helpers
# ---------------------------------------------------------------------------

def _fire(event_name: str, payload: dict) -> None:
    try:
        from simorgh.apps.events.bus import fire_event
        fire_event(event_name, payload)
    except Exception:
        pass
