from django.db import models
from django.db.models.sql.query import Q
from . import SideStoreModel, Tournament, GroupStage, Match
import uuid
from django.utils import timezone
from django.db.models import Count

class TeamRegistration(SideStoreModel):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=True)
    tournament = models.ForeignKey(Tournament, on_delete=models.SET_NULL, related_name='team_registrations', null=True)
    group_stage = models.ForeignKey(GroupStage, null=True, blank=True, on_delete=models.SET_NULL, related_name='team_registrations')
    registration_date = models.DateTimeField(null=True, blank=True)
    call_date = models.DateTimeField(null=True, blank=True)
    bracket_position = models.IntegerField(null=True, blank=True)
    group_stage_position = models.IntegerField(null=True, blank=True)
    comment = models.CharField(max_length=200, null=True, blank=True)
    source = models.CharField(max_length=20, null=True, blank=True)
    source_value = models.CharField(max_length=200, null=True, blank=True)
    logo = models.CharField(max_length=200, null=True, blank=True) #models.FilePathField(path=os.path.join(settings.STATIC_ROOT, "images"), null=True, blank=True)
    name = models.CharField(max_length=200, null=True, blank=True)

    walk_out = models.BooleanField(default=False)
    wild_card_bracket = models.BooleanField(default=False)
    wild_card_group_stage = models.BooleanField(default=False)
    weight = models.IntegerField(default=0)
    locked_weight = models.IntegerField(null=True, blank=True)

    confirmation_date = models.DateTimeField(null=True, blank=True)
    qualified = models.BooleanField(default=False)

    final_ranking = models.IntegerField(null=True, blank=True)
    points_earned = models.IntegerField(null=True, blank=True)

    def delete_dependencies(self):
        for player_registration in self.player_registrations.all():
            # player_registration.delete_dependencies()
            player_registration.delete()
        for team_score in self.team_scores.all():
            # match.delete_dependencies()
            team_score.delete()

    def __str__(self):
        if self.name:
            return self.name
            # return f"{self.name}: {self.player_names()}"
        return self.player_names()

    def save(self, *args, **kwargs):
        self.store_id = str(self.get_tournament_id())
        super().save(*args, **kwargs)

    def get_tournament_id(self):
        if self.tournament:
            return self.tournament.id
        else:
            return None

    def player_names_as_list(self):
        players = list(self.player_registrations.all())
        if len(players) == 0:
            return []
        elif len(players) == 1:
            return [players[0].name()]
        else:
            return [pr.name() for pr in players]

    def team_names(self):
        if self.name:
            return [self.name] #add an empty line if it's a team name
        else:
            return self.player_names_as_list()

    def shortened_team_names(self):
        if self.name:
            return [self.name] #add an empty line if it's a team name
        else:
            players = list(self.player_registrations.all())
            if len(players) == 0:
                if self.wild_card_bracket:
                    return ['Place réservée wildcard']
                elif self.wild_card_group_stage:
                    return ['Place réservée wildcard']
                else:
                    return ['Place réservée']
            elif len(players) == 1:
                return [players[0].shortened_name()]
            else:
                return [pr.shortened_name() for pr in players]

    @property
    def players(self):
        # Fetch related PlayerRegistration objects
        return self.player_registrations.all().order_by('rank')

    def player_names(self):
        names = self.player_names_as_list()
        str = " - ".join(names)
        if len(str) > 0:
            return str
        else:
            return "no players"

    def formatted_team_names(self):
        if self.name:
            return self.name
        names = [pr.last_name for pr in self.player_registrations.all()][:2]  # Take max first 2
        joined_names = " / ".join(names)
        if joined_names:
            return f"Paire {joined_names}"
        return "Détail de l'équipe"

    def next_match(self):
        all_matches = [ts.match for ts in self.team_scores.all() if ts.match is not None]
        now = timezone.now()
        all_matches = sorted(all_matches, key=lambda m: m.start_date if m.start_date is not None else now)
        matches = [m for m in all_matches if m.end_date is None]
        if matches:
            return matches[0]
        else:
            return None

    def next_stage(self):
        matches = map(lambda ts: ts.match, self.team_scores.all())
        matches = [m for m in matches if m.group_stage is None]
        matches = sorted(matches, key=lambda m: m.round.index)

        # matches = self.teamscore_set
        # matches = Match.objects.filter(group_stage__isnull=True, team_scores__player_registrations__id=self.id).order_by('round__index')
        # print(f"matches = {len(matches)}")
        if matches:
            return matches[0].round.name()
        elif self.group_stage:
            return self.group_stage.name()
        else:
            return "--"

    def set_weight(self):
        self.weight = self.player_registrations.aggregate(total_weight=models.Sum('computed_rank'))['total_weight'] or 0
        self.save()  # Save the updated weight if necessary

    def is_valid_for_summon(self):
        return self.player_registrations.count() > 0 or self.name is not None

    def initial_weight(self):
        if self.locked_weight is None:
            return self.weight
        else:
            return self.locked_weight

    def local_call_date(self):
        timezone = self.tournament.timezone()
        if self.call_date:
            return self.call_date.astimezone(timezone)
        else:
            # print("no date")
            return None

    def local_registration_date(self):
        timezone = self.tournament.timezone()
        if self.registration_date:
            return self.registration_date.astimezone(timezone)
        else:
            # print("no date")
            return None

    def out_of_tournament(self):
        return self.walk_out

    def get_other_player(self, player):
        for p in self.player_registrations.all():
            if p != player:
                return p
        return None

    def is_in_waiting_list(self):
        return self.tournament.get_team_waiting_list_position(self)

    def get_matches(self):
        matches = Match.objects.filter(team_scores__team_registration=self).distinct()
        print(f"All matches for team {self.id}: {matches.count()}")
        for match in matches:
            print(f"Match {match.id}: start_date={match.start_date}, end_date={match.end_date}")
        return matches

    def get_upcoming_matches(self):
        matches = self.get_matches()
        upcoming = matches.filter(end_date__isnull=True).order_by('start_date')
        print(f"Upcoming matches count: {upcoming.count()}")
        return [match.live_match() for match in upcoming]

    def get_completed_matches(self):
        matches = self.get_matches()
        completed = matches.filter(end_date__isnull=False).order_by('-end_date')
        print(f"Completed matches count: {completed.count()}")
        return [match.live_match() for match in completed]

    def get_statistics(self):

        stats = {
            'final_ranking': self.get_final_ranking(),
            'weight': self.weight,
            'points_earned': self.get_points_earned(),
            'initial_stage': self.get_initial_stage(),
            'matches_played': self.count_matches_played(),
            'victory_ratio': self.calculate_victory_ratio(),
            'team_rank': self.team_rank_label(),
            'total_teams': self.total_teams(),
        }
        return stats

    def team_rank(self):
        teams = self.tournament.teams(False)  # Get list of TeamItem objects
        try:
            # Find the TeamItem that corresponds to this TeamRegistration
            team_index = next(i for i, team in enumerate(teams)
                            if team.team_registration.id == self.id)
            return team_index + 1
        except (StopIteration, ValueError):
            return None

    def team_rank_label(self):
        team_rank = self.team_rank()
        if team_rank is None:
            return "--"
        return f"{team_rank}"

    def total_teams(self):
        teams = self.tournament.teams(False)
        return f"{len(teams)}"

    def get_initial_stage(self):
        matches = self.get_matches().order_by('start_date')
        first_match = matches.first()
        if first_match:
            if first_match.group_stage:
                return "Poule"
            elif first_match.round:
                return first_match.round.name()
        return None


    def get_final_ranking(self):
        if self.final_ranking:
            if self.final_ranking == 1:
                return "1er" + self.ranking_delta()
            return f"{self.final_ranking}ème" + self.ranking_delta()
        return None

    def ranking_delta(self):
        team_rank = self.team_rank()
        if team_rank is None or self.final_ranking is None:
            return ""

        sign = "-"
        if team_rank > self.final_ranking:
            sign = "+"
        if team_rank == self.final_ranking:
            sign = "+"
        return f" ({sign}"+f"{abs(self.final_ranking - team_rank)})"

    def get_points_earned(self):
        return self.points_earned

    def calculate_total_duration(self):
        total_seconds = 0
        for match in self.get_matches().filter(end_date__isnull=False):
            if match.start_date and match.end_date:
                duration = (match.end_date - match.start_date).total_seconds()
                total_seconds += duration

        if total_seconds > 0:
            hours = int(total_seconds // 3600)
            minutes = int((total_seconds % 3600) // 60)
            if hours > 0:
                return f"{hours}h{minutes:02d}"
            return f"{minutes}min"
        return None

    def count_matches_played(self):
        return self.get_matches().filter(end_date__isnull=False).count()

    def calculate_victory_ratio(self):
        matches = self.get_matches().filter(end_date__isnull=False)
        total_matches = matches.count()
        if total_matches > 0:
            wins = matches.filter(winning_team_id=self.id).count()
            # ratio = (wins / total_matches) * 100
            return f"{wins}/{total_matches}"
        return None

    def has_registered_online(self):
        for p in self.player_registrations.all():
            if p.registered_online:
                return True
        return False

    def formatted_special_status(self):
        if self.wild_card_bracket:
            return "(wildcard tableau)"
        if self.wild_card_group_stage:
            return "(wildcard poule)"
        return ""
