"""Calendar plugin models — calendars, entries, links, shares, visibility, subtasks, resources, bookings."""

from __future__ import annotations

import uuid
from datetime import datetime
from typing import Any

from sqlalchemy import (
    Boolean,
    DateTime,
    ForeignKey,
    Index,
    String,
)
from sqlalchemy.dialects.postgresql import JSONB
from sqlalchemy.dialects.postgresql import UUID as PGUUID
from sqlalchemy.orm import Mapped, mapped_column

from app.core.db import Base, TenantMixin


class Calendar(Base, TenantMixin):
    """Calendar entity — tenant-scoped, soft-deletable, owned by a user."""

    __tablename__ = "calendars"
    __table_args__ = (Index("ix_calendars_tenant", "tenant_id"),)

    id: Mapped[uuid.UUID] = mapped_column(
        PGUUID(as_uuid=True), primary_key=True, default=uuid.uuid4
    )
    name: Mapped[str] = mapped_column(String(200), nullable=False)
    color: Mapped[str] = mapped_column(String(20), nullable=False, default="#3B82F6")
    type: Mapped[str] = mapped_column(String(20), nullable=False, default="personal")
    owner_id: Mapped[uuid.UUID] = mapped_column(PGUUID(as_uuid=True), nullable=False)
    ics_token: Mapped[str | None] = mapped_column(String(64), nullable=True)
    deleted_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)


class CalendarEntry(Base, TenantMixin):
    """Calendar entry — appointment or task, tenant-scoped, soft-deletable."""

    __tablename__ = "calendar_entries"
    __table_args__ = (
        Index("ix_entries_tenant_cal", "tenant_id", "calendar_id"),
        Index("ix_entries_tenant_start", "tenant_id", "start_at"),
        Index("ix_entries_tenant_due", "tenant_id", "due_date"),
        Index("ix_entries_assigned", "tenant_id", "assigned_to", "status"),
    )

    id: Mapped[uuid.UUID] = mapped_column(
        PGUUID(as_uuid=True), primary_key=True, default=uuid.uuid4
    )
    calendar_id: Mapped[uuid.UUID] = mapped_column(
        PGUUID(as_uuid=True),
        ForeignKey("calendars.id", ondelete="CASCADE"),
        nullable=False,
    )
    entry_type: Mapped[str] = mapped_column(String(15), nullable=False)
    subtype: Mapped[str] = mapped_column(String(20), nullable=False, default="normal")
    title: Mapped[str] = mapped_column(String(500), nullable=False)
    description: Mapped[str | None] = mapped_column(String, nullable=True)
    start_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
    end_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
    all_day: Mapped[bool] = mapped_column(Boolean, default=False, nullable=False)
    location: Mapped[str | None] = mapped_column(String(500), nullable=True)
    due_date: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
    priority: Mapped[str] = mapped_column(String(10), nullable=False, default="medium")
    status: Mapped[str] = mapped_column(String(15), nullable=False, default="open")
    assigned_to: Mapped[uuid.UUID | None] = mapped_column(PGUUID(as_uuid=True), nullable=True)
    reminder: Mapped[dict[str, Any] | None] = mapped_column(JSONB, nullable=True)
    recurrence: Mapped[dict[str, Any] | None] = mapped_column(JSONB, nullable=True)
    source_mail_id: Mapped[uuid.UUID | None] = mapped_column(PGUUID(as_uuid=True), nullable=True)
    created_by: Mapped[uuid.UUID] = mapped_column(PGUUID(as_uuid=True), nullable=False)
    deleted_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)


class CalendarEntryLink(Base, TenantMixin):
    """Link between a calendar entry and an entity (contact)."""

    __tablename__ = "calendar_entry_links"
    __table_args__ = (Index("ix_entry_links_entry", "entry_id"),)

    id: Mapped[uuid.UUID] = mapped_column(
        PGUUID(as_uuid=True), primary_key=True, default=uuid.uuid4
    )
    entry_id: Mapped[uuid.UUID] = mapped_column(
        PGUUID(as_uuid=True),
        ForeignKey("calendar_entries.id", ondelete="CASCADE"),
        nullable=False,
    )
    entity_type: Mapped[str] = mapped_column(String(50), nullable=False)
    entity_id: Mapped[uuid.UUID] = mapped_column(PGUUID(as_uuid=True), nullable=False)


class CalendarShare(Base, TenantMixin):
    """Calendar sharing — user or group with read/write permission."""

    __tablename__ = "calendar_shares"
    __table_args__ = (Index("ix_calendar_shares_cal", "calendar_id"),)

    id: Mapped[uuid.UUID] = mapped_column(
        PGUUID(as_uuid=True), primary_key=True, default=uuid.uuid4
    )
    calendar_id: Mapped[uuid.UUID] = mapped_column(
        PGUUID(as_uuid=True),
        ForeignKey("calendars.id", ondelete="CASCADE"),
        nullable=False,
    )
    user_id: Mapped[uuid.UUID | None] = mapped_column(PGUUID(as_uuid=True), nullable=True)
    group_id: Mapped[uuid.UUID | None] = mapped_column(PGUUID(as_uuid=True), nullable=True)
    permission: Mapped[str] = mapped_column(String(10), nullable=False)


class UserCalendarVisibility(Base):
    """Per-user calendar visibility toggle."""

    __tablename__ = "user_calendar_visibility"

    user_id: Mapped[uuid.UUID] = mapped_column(
        PGUUID(as_uuid=True),
        ForeignKey("users.id", ondelete="CASCADE"),
        primary_key=True,
    )
    calendar_id: Mapped[uuid.UUID] = mapped_column(
        PGUUID(as_uuid=True),
        ForeignKey("calendars.id", ondelete="CASCADE"),
        primary_key=True,
    )
    tenant_id: Mapped[uuid.UUID] = mapped_column(PGUUID(as_uuid=True), nullable=False)
    visible: Mapped[bool] = mapped_column(Boolean, default=True, nullable=False)


class Subtask(Base, TenantMixin):
    """Subtask belonging to a calendar entry."""

    __tablename__ = "subtasks"
    __table_args__ = (Index("ix_subtasks_entry", "entry_id"),)

    id: Mapped[uuid.UUID] = mapped_column(
        PGUUID(as_uuid=True), primary_key=True, default=uuid.uuid4
    )
    entry_id: Mapped[uuid.UUID] = mapped_column(
        PGUUID(as_uuid=True),
        ForeignKey("calendar_entries.id", ondelete="CASCADE"),
        nullable=False,
    )
    title: Mapped[str] = mapped_column(String(500), nullable=False)
    completed: Mapped[bool] = mapped_column(Boolean, default=False, nullable=False)


class Resource(Base, TenantMixin):
    """Bookable resource — room or equipment."""

    __tablename__ = "resources"
    __table_args__ = (Index("ix_resources_tenant", "tenant_id"),)

    id: Mapped[uuid.UUID] = mapped_column(
        PGUUID(as_uuid=True), primary_key=True, default=uuid.uuid4
    )
    name: Mapped[str] = mapped_column(String(200), nullable=False)
    type: Mapped[str] = mapped_column(String(50), nullable=False)


class ResourceBooking(Base, TenantMixin):
    """Booking of a resource for a calendar entry."""

    __tablename__ = "resource_bookings"
    __table_args__ = (
        Index("ix_bookings_resource", "resource_id"),
        Index("ix_bookings_entry", "entry_id"),
    )

    id: Mapped[uuid.UUID] = mapped_column(
        PGUUID(as_uuid=True), primary_key=True, default=uuid.uuid4
    )
    resource_id: Mapped[uuid.UUID] = mapped_column(
        PGUUID(as_uuid=True),
        ForeignKey("resources.id", ondelete="CASCADE"),
        nullable=False,
    )
    entry_id: Mapped[uuid.UUID] = mapped_column(
        PGUUID(as_uuid=True),
        ForeignKey("calendar_entries.id", ondelete="CASCADE"),
        nullable=False,
    )
    start_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), nullable=False)
    end_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), nullable=False)
