from django.db import models
from . import Tournament, FederalMatchCategory
import uuid
from ..utils.extensions import format_seconds
from datetime import datetime, timedelta
from django.utils import timezone

class GroupStage(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=True)
    tournament = models.ForeignKey(Tournament, on_delete=models.CASCADE)
    index = models.IntegerField(default=0)
    size = models.IntegerField(default=4)
    format = models.IntegerField(default=FederalMatchCategory.NINE_GAMES, choices=FederalMatchCategory.choices, null=True, blank=True)
    start_date = models.DateTimeField(null=True, blank=True)
    name = models.CharField(max_length=200, null=True, blank=True)

    def __str__(self):
        return self.display_name()
        # return f"{self.tournament.display_name()} - {self.display_name()}"

    def display_name(self):
        if self.name:
            return self.name
        else:
            return f"Poule {self.index + 1}"

    def next_match(self, player_registration):
        matches = self.matches_for_registration(player_registration).filter(end_date__isnull=False).order_by('start_date')
        return matches[0]

    def matches_for_registration(self, player_registration):
        team_scores = TeamScore.objects.filter(player_registrations=player_registration)
        return [ts.match for ts in team_scores] # map(lambda ts: ts.match, team_scores)

    def live_group_stages(self):
        lgs = LiveGroupStage(self.display_name())
        gs_teams = {}

        # init all teams
        for team_registration in self.teamregistration_set.all():
            if team_registration in gs_teams:
                team = gs_teams[team_registration]
            else:
                team = GroupStageTeam(team_registration)
                gs_teams[team_registration] = team

        # compute matches
        for match in self.match_set.all():
            lgs.add_match(match)
            team_scores = match.team_scores.all()
            if len(team_scores) == 2:

                ts1 = team_scores[0]
                ts2 = team_scores[1]
                scores1 = ts1.scores()
                scores2 = ts2.scores()

                if match.winning_team_id:

                    for team_score in match.team_scores.all():
                        team_registration = team_score.team_registration
                        if team_registration in gs_teams:
                            team = gs_teams[team_registration]
                            if match.winning_team_id == team_registration.id:
                                team.wins += 1
                            else:
                                team.losses += 1

                    total1 = 0
                    total2 = 0

                    if len(scores1) == len(scores2):
                        if len(scores1) > 1: # multiple sets
                            for i in range(len(scores1)):
                                if scores1[i] > scores2[i]:
                                    total1 += 1
                                else:
                                    total2 += 1
                        elif len(scores1) == 1:
                            total1 = scores1[0]
                            total2 = scores2[0]

                    if ts1.team_registration in gs_teams and ts2.team_registration in gs_teams:
                        team1 = gs_teams[ts1.team_registration]
                        team2 = gs_teams[ts2.team_registration]
                        team1.diff += total1 - total2
                        team2.diff += total2 - total1

        if len(self.match_set.filter(end_date__isnull=False).all()) > 0:
            teams = sorted(gs_teams.values(), key=lambda team: -(team.wins * 100 + team.diff))
        else:
            teams = sorted(gs_teams.values(), key=lambda team: team.position)

        for team in teams:
            lgs.add_team(team)
        return lgs

    def starts_soon(self):
        if self.start_date:
            early_start = self.start_date - timedelta(minutes=30)
            return timezone.now() > early_start
        else:
            return False

class LiveGroupStage:
    def __init__(self, title):
        self.title = title
        self.teams = []
        self.start = None
        self.end = None

    def add_match(self, match):
        if self.start and match.start_date and match.start_date < self.start:
            self.start = match.start_date
        elif not self.start:
            self.start = match.start_date
        if self.end and match.end_date and match.end_date > self.end:
            self.end = match.end_date
        elif not self.end:
            self.end = match.end_date

    def add_team(self, team):
        self.teams.append(team)

    def formatted_duration(self):
        if self.start and self.end:
            return format_seconds((self.end - self.start).total_seconds())
        else:
            return ""

    def to_dict(self):
        return {
            "title": self.title,
            "teams": [team.to_dict() for team in self.teams],
            "duration": self.formatted_duration()
        }

class GroupStageTeam:
    def __init__(self, team_registration):
        self.names = team_registration.shortened_team_names()
        if team_registration.group_stage_position:
            self.position = team_registration.group_stage_position
        else:
            self.position = 0
        self.wins = 0
        self.losses = 0
        self.diff = 0
        self.weight = team_registration.weight

    def wins_losses(self):
        return f"{self.wins}/{self.losses}"

    def match_count(self):
        return self.wins + self.losses

    def formatted_diff(self):
        if self.diff >= 0:
            return f"+{self.diff}"
        else:
            return f"{self.diff}"

    def to_dict(self):
        return {
            "names": self.names,
            "win_loss": self.wins_losses(),
            "diff": self.formatted_diff(),
            "weight": self.weight,
            "match_count": self.match_count(),
        }
