from dataclasses import dataclass
from typing import Optional, TypedDict

from django.apps import apps
from django.db import models
from django.urls import reverse
from scrobbles.dataclasses import BaseLogData, WithPeopleLogData
from scrobbles.mixins import ScrobblableConstants, ScrobblableMixin

BNULL = {"blank": True, "null": True}


class DiscGolfSingleScores(TypedDict, total=False):
    person_id: int
    total: int


class DiscGolfTeamScores(TypedDict, total=False):
    person_ids: list[int]
    total: int


@dataclass
class DiscGolfLogData(BaseLogData, WithPeopleLogData):
    scores: Optional[dict[str, DiscGolfSingleScores | DiscGolfTeamScores]] = None
    weather: Optional[str] = None
    fun_factor: Optional[str] = None
    course_name: Optional[str] = None
    par: Optional[int] = None
    round_type: Optional[str] = None


class DiscGolfCourse(ScrobblableMixin):
    description = models.TextField(**BNULL)
    layout_name = models.CharField(max_length=255, **BNULL)
    number_of_holes = models.IntegerField(**BNULL)
    par_total = models.IntegerField(**BNULL)
    par_per_hole = models.JSONField(**BNULL)
    trail = models.ForeignKey(
        "trails.Trail", on_delete=models.DO_NOTHING, **BNULL
    )
    pdga_slug = models.CharField(max_length=255, **BNULL)
    udisc_id = models.CharField(max_length=255, **BNULL)

    @property
    def pdga_link(self) -> str:
        if self.pdga_slug:
            return f"https://www.pdga.com/course-directory/course/{self.pdga_slug}/"
        return ""

    @property
    def udisc_link(self) -> str:
        if self.udisc_id:
            return f"https://udisc.com/courses/{self.udisc_id}/"
        return ""

    def get_absolute_url(self) -> str:
        return reverse("discgolf:course_detail", kwargs={"slug": self.uuid})

    def __str__(self):
        return f"{self.title} ({self.layout_name or 'Default'})"

    @property
    def logdata_cls(self):
        return DiscGolfLogData

    @property
    def subtitle(self):
        return self.layout_name or ""

    @property
    def strings(self) -> ScrobblableConstants:
        return ScrobblableConstants(verb="Playing", tags="golf")

    @property
    def primary_image_url(self) -> str:
        return ""

    @classmethod
    def find_or_create(cls, name: str, **defaults) -> "DiscGolfCourse":
        course = cls.objects.filter(title=name).first()
        if not course:
            course = cls.objects.create(title=name, **defaults)
        return course

    def scrobbles(self, user_id):
        Scrobble = apps.get_model("scrobbles", "Scrobble")
        return Scrobble.objects.filter(user_id=user_id, disc_golf_course=self).order_by(
            "-timestamp"
        )
