import typing
from datetime import datetime
from xmlrpc.client import DateTime

from sqlmodel import Field, Relationship, SQLModel, String

WorkTypes = typing.Literal["cooking", "dishes", "tables"]


class Event(SQLModel, table=True):
    id: int | None = Field(default=None, primary_key=True)
    title: str = Field(nullable=False)
    event_time: datetime = Field(nullable=False)
    registration_deadline: datetime = Field(nullable=False)
    description: str
    recipe_link: str

    # Min and max number of people needed for cooking, doing the dishes and preparing the tables
    team_cooking_min: int = 3
    team_cooking_max: int = 5

    team_dishes_min: int = 3
    team_dishes_max: int = 5

    # Todo: Rename to "table"
    team_prep_min: int = 1
    team_prep_max: int = 1

    registrations: list["Registration"] = Relationship()
    team: list["TeamRegistration"] = Relationship()

    def team_min_reached(self, work_type: WorkTypes):
        threshold = {
            "cooking": self.team_cooking_min,
            "dishes": self.team_dishes_min,
            "tables": self.team_prep_min,
        }[work_type]
        return sum(1 for t in self.team if t.work_type == work_type) >= threshold

    def team_max_reached(self, work_type: WorkTypes):
        threshold = {
            "cooking": self.team_cooking_max,
            "dishes": self.team_dishes_max,
            "tables": self.team_prep_max,
        }[work_type]
        return sum(1 for t in self.team if t.work_type == work_type) >= threshold

    def all_teams_min(self):
        return all(
            self.team_min_reached(work_type) for work_type in typing.get_args(WorkTypes)
        )

    def all_teams_max(self):
        return all(
            self.team_max_reached(work_type) for work_type in typing.get_args(WorkTypes)
        )


class TeamRegistration(SQLModel, table=True):
    id: int | None = Field(default=None, primary_key=True)
    event_id: int | None = Field(default=None, foreign_key="event.id")
    person_name: str = Field(nullable=False)
    work_type: WorkTypes = Field(nullable=False, sa_type=String)
    comment: str | None


class Household(SQLModel, table=True):
    id: int | None = Field(default=None, primary_key=True)
    name: str = Field(nullable=False)


class Registration(SQLModel, table=True):
    event_id: int | None = Field(default=None, foreign_key="event.id", primary_key=True)
    household_id: int | None = Field(
        default=None, foreign_key="household.id", primary_key=True
    )
    num_adult_meals: int
    num_children_meals: int
    num_small_children_meals: int
    comment: str | None

    household: Household = Relationship()


class Subscription(SQLModel, table=True):
    household_id: int | None = Field(
        default=None, foreign_key="household.id", primary_key=True
    )
    num_adult_meals: int
    num_children_meals: int
    num_small_children_meals: int
    comment: str | None

    last_modified: datetime = Field(default_factory=datetime.now, nullable=False)

    monday: bool = True
    tuesday: bool = True
    wednesday: bool = True
    thursday: bool = True
    friday: bool = True
    saturday: bool = True
    sunday: bool = True

    household: Household = Relationship()

    def day_string_de(self) -> str:
        """
        Generates a string representation of selected days in German short form.
        """
        result = []

        if self.monday:
            result.append("Mo")
        if self.tuesday:
            result.append("Di")
        if self.wednesday:
            result.append("Mi")
        if self.thursday:
            result.append("Do")
        if self.friday:
            result.append("Fr")
        if self.saturday:
            result.append("Sa")
        if self.sunday:
            result.append("So")

        if len(result) < 7:
            return ", ".join(result)
        else:
            return "Alle"
