from usuarios.permissions import IsClubAdmin, IsClubStaff
import json
from json import JSONDecodeError

from django.shortcuts import render
from drf_yasg import openapi
from drf_yasg.utils import swagger_auto_schema
from rest_framework import status
from rest_framework.decorators import api_view, permission_classes
from rest_framework.permissions import AllowAny, IsAuthenticated
from rest_framework.response import Response
from django.db import transaction
from django.db.utils import IntegrityError
from usuarios.models import Equipos, Usuarios, UsersTeams


# Create your views here.
@swagger_auto_schema(
    method='post',
    operation_description="Asigna un equipo a usuarios",
    tags=["Equipos"],
    security=[{'Bearer': []}],
    request_body=openapi.Schema(
        type=openapi.TYPE_OBJECT,
        properties={
            "team_id": openapi.Schema(type=openapi.TYPE_STRING, description="Id del equipo"),
            "user_ids": openapi.Schema(type=openapi.TYPE_ARRAY,
                items=openapi.Schema(type=openapi.TYPE_INTEGER),  # <-- items es obligatorio para arrays
                description="Ids de los usuarios asignados",
                example=[1, 2, 3])
        },
        required=["team_id", "user_ids"],
    ),
    responses={
        201: openapi.Response(description="Usuarios asignados con éxito"),
        400: openapi.Response(description="Solicitud inválida"),
    },
)
@api_view(['POST'])
@permission_classes([IsClubAdmin])
def asignarEquipo(request):
    """
        Asigna los user_ids a team_id. Devuelve resumen.
        - Crea solo las relaciones que no existan.
        - Usa bulk_create con ignore_conflicts para eficiencia (si tu Django lo soporta).
        """
    body = json.loads(request.body)
    team_id = body.get("team_id")
    user_ids = body.get("user_ids")
    result = {
        "team_id": team_id,
        "requested_user_ids": user_ids,
        "created": [],
        "skipped_already_assigned": [],
        "missing_users": [],
        "error": None,
    }

    # Validar equipo
    try:
        team = Equipos.objects.get(id=team_id)
    except Equipos.DoesNotExist:
        result["error"] = f"Team con id {team_id} no existe."
        return Response(result)

    # Obtener usuarios existentes
    users_qs = Usuarios.objects.filter(id__in=user_ids)
    existing_user_ids = set(users_qs.values_list('id', flat=True))
    missing = [uid for uid in user_ids if uid not in existing_user_ids]
    result["missing_users"] = missing

    # Filtrar solo usuarios existentes
    users = list(users_qs)

    if not users:
        return Response(result)

    # Relaciones ya existentes
    already_qs = UsersTeams.objects.filter(idTeam=team, idUser__id__in=existing_user_ids)
    already_assigned_ids = set(already_qs.values_list('idUser__id', flat=True))
    result["skipped_already_assigned"] = list(already_assigned_ids)

    # Preparar creaciones faltantes
    to_create = []
    for u in users:
        if u.id in already_assigned_ids:
            continue
        # usa los nombres actuales de tu modelo: idUser/idTeam
        to_create.append(UsersTeams(idUser=u, idTeam=team))

    if not to_create:
        return Response(result)

    try:
        with transaction.atomic():
            # bulk_create puede aceptar ignore_conflicts=True en Django moderno
            created_objs = UsersTeams.objects.bulk_create(to_create, ignore_conflicts=True)
            # bulk_create puede no devolver ids en algunos backends; igual, devolvemos cuáles se intentaron crear
            result["created"] = [getattr(obj, "id", None) for obj in created_objs]
    except (IntegrityError, TypeError):
        # Fallback por si bulk_create no soporta ignore_conflicts o hay race
        created = []
        for obj in to_create:
            ut, created_flag = UsersTeams.objects.get_or_create(idUser=obj.idUser, idTeam=obj.idTeam)
            if created_flag:
                created.append(ut.id)
        result["created"] = created

    return Response(result)

@swagger_auto_schema(
    method='post',
    operation_description="Quita a un usuario de un equipo",
    tags=["Equipos"],
    security=[{'Bearer': []}],
    request_body=openapi.Schema(
        type=openapi.TYPE_OBJECT,
        properties={
            "team_id": openapi.Schema(type=openapi.TYPE_INTEGER, description="Id del equipo"),
            "user_id": openapi.Schema(type=openapi.TYPE_INTEGER, description="Id del usuario"),
        },
        required=["team_id", "user_id"],
    ),
    responses={
        200: openapi.Response(description="Usuario quitado del equipo"),
        400: openapi.Response(description="Solicitud inválida"),
        404: openapi.Response(description="El usuario no pertenece al equipo"),
    },
)
@api_view(['POST'])
@permission_classes([IsClubAdmin])
def quitarEquipo(request):
    try:
        body = json.loads(request.body)
        team_id = int(body.get("team_id"))
        user_id = int(body.get("user_id"))
    except (JSONDecodeError, TypeError, ValueError):
        return Response({"message": "team_id y user_id son obligatorios"}, status=400)

    deleted, _ = UsersTeams.objects.filter(idTeam_id=team_id, idUser_id=user_id).delete()
    if not deleted:
        return Response({"message": "El usuario no pertenece al equipo"}, status=404)
    return Response({"message": "Usuario quitado del equipo"}, status=200)

@swagger_auto_schema(
    method='get',
    operation_description="Obtener usuarios asignados a un equipo",
    tags=["Equipos"],
    security=[{'Bearer': []}],
    responses={
        200: openapi.Response(
            description="Usuarios asignados"
        ),
        400: openapi.Response(description="Ocurrió un error"),
    },
)
@api_view(['GET'])
@permission_classes([IsAuthenticated])
def verAsignadosEquipo(request, idTeam):
    try:
        id_team_int = int(idTeam)
    except (TypeError, ValueError):
        return Response({"message": "team_id inválido"}, status=400)

        # verificar existencia del equipo
    if not Equipos.objects.filter(id=id_team_int).exists():
        return Response(
            {"message": f"Equipo con id {id_team_int} no encontrado", "team_id": id_team_int, "data": []},
            status=404
        )

        # consulta eficiente: filtrar por FK directa y traer solo campos necesarios
    rows = UsersTeams.objects.filter(
        idTeam_id=id_team_int,
        idUser__isnull=False
    ).select_related('idUser').values(
        'idUser__id', 'idUser__name', 'idUser__username', 'idUser__email'
    )

    data = [
        {
            "id": r['idUser__id'],
            "name": r['idUser__name'],
            "username": r['idUser__username'],
            "email": r['idUser__email'],
        }
        for r in rows
    ]

    if not data:
        return Response({
            "message": f"No hay usuarios asignados al equipo {id_team_int}",
            "team_id": id_team_int,
            "data": []
        }, status=200)

    return Response({
        "message": "Usuarios encontrados",
        "team_id": id_team_int,
        "data": data
    }, status=200)

@swagger_auto_schema(
    method='get',
    operation_description="Obtener los equipos de un usuario",
    tags=["Equipos"],
    security=[{'Bearer': []}],
    responses={
        200: openapi.Response(
            description="Equipos encontrados"
        ),
        400: openapi.Response(description="Ocurrió un error"),
    },
)
@api_view(['GET'])
@permission_classes([IsAuthenticated])
def obtenerEquiposByUser(request, user_id):
    try:
        if not UsersTeams.objects.filter(idUser=user_id).exists():
            return Response(
                {"message": f"Usuario con id {user_id} no encontrado", "data": []},
                status=status.HTTP_400_BAD_REQUEST
            )

        user_teams = UsersTeams.objects.filter(
            idUser=user_id
        ).select_related('idTeam')

        equipos_info = [
            {
                'id': ut.idTeam.id,
                'description': ut.idTeam.description,
                'category': ut.idTeam.category,
                'level': ut.idTeam.level,
                'division': ut.idTeam.division,
                'color': ut.idTeam.color
            }
            for ut in user_teams if ut.idTeam
        ]

        return Response({"message": "Equipos encontrados", "data": equipos_info}, status=status.HTTP_200_OK)
    except json.JSONDecodeError:
        return Response({"message": "Ocurrio un error inesperado"}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)