"""
Servicios para consultar datos deportivos desde tikistats_internal
filtrados por permisos del usuario.
"""

from django.db.models import Q
from .models import Team, TeamDivision, Match, Player, Competition, Division


class SportsDataService:
    """
    Servicio para obtener datos deportivos respetando permisos del usuario.
    
    Uso:
    ----
    from clients.permissions import PermissionChecker
    from router_sports.services import SportsDataService
    
    checker = PermissionChecker(request.user)
    service = SportsDataService(checker)
    
    teams = service.get_accessible_teams()
    matches = service.get_accessible_matches()
    """
    
    def __init__(self, permission_checker):
        """
        Args:
            permission_checker: Instancia de PermissionChecker del usuario
        """
        self.checker = permission_checker
    
    # ============================================
    # TEAMS
    # ============================================
    
    def get_accessible_teams(self):
        """
        Retorna QuerySet de equipos que el usuario puede ver.
        
        Returns:
            QuerySet[Team]: Equipos permitidos
        """
        allowed_team_ids = self.checker.get_allowed_teams()
        
        if allowed_team_ids is None:
            # Superusuario → todos los equipos
            return Team.objects.using('tikistats_internal').all()
        elif allowed_team_ids:
            # Equipos específicos permitidos
            return Team.objects.using('tikistats_internal').filter(id__in=allowed_team_ids)
        else:
            # Sin permisos
            return Team.objects.using('tikistats_internal').none()
    
    def get_team(self, team_id):
        """
        Obtiene un equipo específico si el usuario tiene permiso.
        
        Args:
            team_id: ID del equipo
        
        Returns:
            Team o None si no tiene permiso
        """
        if not self.checker.can_view_team(team_id):
            return None
        
        try:
            return Team.objects.using('tikistats_internal').get(id=team_id)
        except Team.DoesNotExist:
            return None
    
    # ============================================
    # MATCHES
    # ============================================
    
    def get_accessible_matches(self, limit=None, division_id=None):
        """
        Retorna QuerySet de partidos que el usuario puede ver.
        
        Args:
            limit: Número máximo de partidos a retornar
            division_id: Filtrar por división específica
        
        Returns:
            QuerySet[Match]: Partidos permitidos
        """
        allowed_team_ids = self.checker.get_allowed_teams()
        
        # Base queryset
        matches = Match.objects.using('tikistats_internal').select_related(
            'home_team_division__team',
            'away_team_division__team',
            'home_team_division__division',
            'competition'
        ).order_by('-date')
        
        # Filtrar por división si se especifica
        if division_id:
            matches = matches.filter(
                home_team_division__division_id=division_id
            )
        
        # Aplicar filtro de permisos
        if allowed_team_ids is None:
            # Superusuario → todos los partidos
            pass
        elif allowed_team_ids:
            # Filtrar por equipos permitidos
            matches = matches.filter(
                Q(home_team_division__team_id__in=allowed_team_ids) |
                Q(away_team_division__team_id__in=allowed_team_ids)
            )
        else:
            # Sin permisos
            matches = matches.none()
        
        # Aplicar límite si se especifica
        if limit:
            matches = matches[:limit]
        
        return matches
    
    def get_match(self, match_id):
        """
        Obtiene un partido específico si el usuario tiene permiso.
        
        Args:
            match_id: ID del partido
        
        Returns:
            Match o None si no tiene permiso
        """
        if not self.checker.can_view_match(match_id):
            return None
        
        try:
            return Match.objects.using('tikistats_internal').select_related(
                'home_team_division__team',
                'away_team_division__team',
                'competition'
            ).get(id=match_id)
        except Match.DoesNotExist:
            return None
    
    def get_matches_by_team(self, team_id, limit=20):
        """
        Obtiene partidos de un equipo específico.
        
        Args:
            team_id: ID del equipo
            limit: Número máximo de partidos
        
        Returns:
            QuerySet[Match]: Partidos del equipo (si tiene permiso)
        """
        if not self.checker.can_view_team(team_id):
            return Match.objects.using('tikistats_internal').none()
        
        return Match.objects.using('tikistats_internal').filter(
            Q(home_team_division__team_id=team_id) |
            Q(away_team_division__team_id=team_id)
        ).select_related(
            'home_team_division__team',
            'away_team_division__team',
            'competition'
        ).order_by('-date')[:limit]
    
    # ============================================
    # PLAYERS
    # ============================================
    
    def get_accessible_players(self):
        """
        Retorna QuerySet de jugadores que el usuario puede ver.
        
        Returns:
            QuerySet[Player]: Jugadores permitidos
        """
        allowed_player_ids = self.checker.get_allowed_players()
        
        if allowed_player_ids is None:
            # Superusuario → todos los jugadores
            return Player.objects.using('tikistats_internal').all()
        elif allowed_player_ids:
            # Jugadores específicos permitidos
            return Player.objects.using('tikistats_internal').filter(id__in=allowed_player_ids)
        else:
            # Sin permisos
            return Player.objects.using('tikistats_internal').none()
    
    def get_players_by_team(self, team_id, division_id=None):
        """
        Obtiene jugadores de un equipo (con o sin división específica).
        
        Args:
            team_id: ID del equipo
            division_id: ID de la división (opcional)
        
        Returns:
            QuerySet[Player]: Jugadores del equipo
        """
        if not self.checker.can_view_team(team_id):
            return Player.objects.using('tikistats_internal').none()
        
        # Filtrar TeamDivisionPlayer
        team_division_players = TeamDivisionPlayer.objects.using('tikistats_internal').filter(
            team_division__team_id=team_id,
            state='active'
        )
        
        if division_id:
            team_division_players = team_division_players.filter(
                team_division__division_id=division_id
            )
        
        player_ids = team_division_players.values_list('player_id', flat=True)
        
        return Player.objects.using('tikistats_internal').filter(
            id__in=player_ids
        ).select_related('position', 'nationality')
    
    # ============================================
    # DIVISIONS
    # ============================================
    
    def get_divisions(self):
        """Retorna todas las divisiones disponibles"""
        return Division.objects.using('tikistats_internal').all()
    
    def get_division(self, division_id):
        """
        Obtiene una división específica.
        
        Args:
            division_id: ID de la división
        
        Returns:
            Division o None
        """
        try:
            return Division.objects.using('tikistats_internal').get(id=division_id)
        except Division.DoesNotExist:
            return None
    
    # ============================================
    # COMPETITIONS
    # ============================================
    
    def get_competitions(self, division_id=None):
        """
        Retorna competiciones (opcionalmente filtradas por división).
        
        Args:
            division_id: ID de la división (opcional)
        
        Returns:
            QuerySet[Competition]
        """
        competitions = Competition.objects.using('tikistats_internal').select_related(
            'division', 'region'
        ).order_by('-start_date')
        
        if division_id:
            competitions = competitions.filter(division_id=division_id)
        
        return competitions
    
    # ============================================
    # ESTADÍSTICAS
    # ============================================
    
    def get_team_stats(self, team_id):
        """
        Obtiene estadísticas básicas de un equipo.
        
        Args:
            team_id: ID del equipo
        
        Returns:
            dict con estadísticas o None si no tiene permiso
        """
        if not self.checker.can_view_team(team_id, depth='historic'):
            return None
        
        matches = self.get_matches_by_team(team_id, limit=100)
        
        total_matches = matches.count()
        home_matches = matches.filter(home_team_division__team_id=team_id).count()
        away_matches = matches.filter(away_team_division__team_id=team_id).count()
        
        return {
            'total_matches': total_matches,
            'home_matches': home_matches,
            'away_matches': away_matches,
        }