from datetime import datetime
from typing import TYPE_CHECKING, Dict, List, Optional

from pydantic import root_validator
from sqlalchemy import Column
from sqlmodel import Field, Relationship, SQLModel

from .event_attendance import EventAttendance
from .types import TimeStamp

if TYPE_CHECKING:
    from .feedback import Feedback, FeedbackList
    from .participant import Participant, ParticipantList


class EventBase(SQLModel):
    name: str

    code: str

    valid_from: datetime = Field(
        sa_column=Column(
            TimeStamp(timezone=True),
            default=datetime.now,
            nullable=False,
        )
    )
    valid_until: datetime = Field(
        sa_column=Column(
            TimeStamp(timezone=True),
            default=datetime.now,
            nullable=False,
        )
    )

    enabled: bool = Field(default=True, nullable=False)

    @root_validator()
    def range_is_positive(cls, values: Dict[str, datetime]):
        start, end = values.get("valid_from"), values.get("valid_until")
        if start is None or end is None:
            return values
        elif end < start:
            raise ValueError("validity range cannot be negative")

        return values


class Event(EventBase, table=True):
    __tablename__ = "events"

    id: Optional[int] = Field(default=None, primary_key=True, nullable=False)

    attendees: List["Participant"] = Relationship(
        back_populates="attended",
        link_model=EventAttendance,
    )
    feedback: List["Feedback"] = Relationship(
        back_populates="event",
        sa_relationship_kwargs={"cascade": "all, delete, delete-orphan"},
    )


class EventCreate(SQLModel):
    name: str

    valid_from: datetime
    valid_until: datetime


class EventList(SQLModel):
    id: int
    name: str

    code: str
    enabled: bool


class EventRead(EventBase):
    id: int

    feedback: List["FeedbackList"]
    attendees: List["ParticipantList"]


class EventUpdate(SQLModel):
    name: Optional[str]

    valid_from: Optional[datetime]
    valid_until: Optional[datetime]

    enabled: Optional[bool]

pydantic.root_validator sqlmodel.Field sqlmodel.Relationship
[((838, 873), 'sqlmodel.Field', 'Field', ([], {'default': '(True)', 'nullable': '(False)'}), '(default=True, nullable=False)\n', (843, 873), False, 'from sqlmodel import Field, Relationship, SQLModel\n'), ((880, 896), 'pydantic.root_validator', 'root_validator', ([], {}), '()\n', (894, 896), False, 'from pydantic import root_validator\n'), ((1305, 1358), 'sqlmodel.Field', 'Field', ([], {'default': 'None', 'primary_key': '(True)', 'nullable': '(False)'}), '(default=None, primary_key=True, nullable=False)\n', (1310, 1358), False, 'from sqlmodel import Field, Relationship, SQLModel\n'), ((1397, 1464), 'sqlmodel.Relationship', 'Relationship', ([], {'back_populates': '"""attended"""', 'link_model': 'EventAttendance'}), "(back_populates='attended', link_model=EventAttendance)\n", (1409, 1464), False, 'from sqlmodel import Field, Relationship, SQLModel\n'), ((1521, 1627), 'sqlmodel.Relationship', 'Relationship', ([], {'back_populates': '"""event"""', 'sa_relationship_kwargs': "{'cascade': 'all, delete, delete-orphan'}"}), "(back_populates='event', sa_relationship_kwargs={'cascade':\n    'all, delete, delete-orphan'})\n", (1533, 1627), False, 'from sqlmodel import Field, Relationship, SQLModel\n')]