import uuid
from pathlib import Path

from django.contrib.auth import authenticate
from django.db import transaction
from rest_framework import status
from rest_framework.authtoken.models import Token
from rest_framework.decorators import api_view, parser_classes, permission_classes
from rest_framework.parsers import FormParser, MultiPartParser
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response

from apps.common.api import get_current_team

from .models import TeamMember, User
from .serializers import LoginSerializer, RegisterSerializer, TeamMemberSerializer, TeamSerializer, UserSerializer


def auth_payload(user, team, token):
    return {
        "token": token.key,
        "user": UserSerializer(user).data,
        "team": TeamSerializer(team).data,
    }


@api_view(["POST"])
@permission_classes([])
def register(request):
    serializer = RegisterSerializer(data=request.data)
    serializer.is_valid(raise_exception=True)
    data = serializer.save()
    token, _ = Token.objects.get_or_create(user=data["user"])
    return Response(auth_payload(data["user"], data["team"], token), status=status.HTTP_201_CREATED)


@api_view(["POST"])
@permission_classes([])
def login(request):
    serializer = LoginSerializer(data=request.data)
    serializer.is_valid(raise_exception=True)
    user = authenticate(
        request,
        username=serializer.validated_data["username"],
        password=serializer.validated_data["password"],
    )
    if user is None or user.is_disabled:
        return Response({"detail": "invalid credentials"}, status=status.HTTP_400_BAD_REQUEST)
    team = get_current_team(user)
    token, _ = Token.objects.get_or_create(user=user)
    return Response(auth_payload(user, team, token))


@api_view(["POST"])
@permission_classes([IsAuthenticated])
def logout(request):
    Token.objects.filter(user=request.user).delete()
    return Response(status=status.HTTP_204_NO_CONTENT)


@api_view(["GET", "PATCH"])
@permission_classes([IsAuthenticated])
def me(request):
    user = request.user
    if request.method == "PATCH":
        if "name" in request.data:
            user.first_name = str(request.data.get("name") or "").strip()
        if "phone" in request.data:
            user.phone = str(request.data.get("phone") or "").strip()[:32]
        email = str(request.data.get("email") or "").strip()
        if email:
            user.email = email
        user.save(update_fields=["first_name", "phone", "email"])
    team = get_current_team(user)
    return Response(
        {
            "user": UserSerializer(user).data,
            "team": TeamSerializer(team).data,
        }
    )


@api_view(["POST"])
@permission_classes([IsAuthenticated])
def change_password(request):
    user = request.user
    old_password = str(request.data.get("old_password") or "")
    new_password = str(request.data.get("new_password") or "").strip()
    if not user.check_password(old_password):
        return Response({"old_password": ["原密码不正确"]}, status=status.HTTP_400_BAD_REQUEST)
    if len(new_password) < 8:
        return Response({"new_password": ["新密码至少 8 位"]}, status=status.HTTP_400_BAD_REQUEST)
    user.set_password(new_password)
    user.save(update_fields=["password"])
    Token.objects.filter(user=user).delete()
    token, _ = Token.objects.get_or_create(user=user)
    return Response({"token": token.key})


@api_view(["POST"])
@parser_classes([MultiPartParser, FormParser])
@permission_classes([IsAuthenticated])
def update_avatar(request):
    from apps.assets.storage import TosStorage

    upload = request.FILES.get("file")
    if upload is None:
        return Response({"detail": "no file"}, status=status.HTTP_400_BAD_REQUEST)
    user = request.user
    suffix = Path(upload.name).suffix.lower() or ".png"
    object_key = f"users/{user.id}/avatar/{uuid.uuid4()}{suffix}"
    storage = TosStorage()
    storage.upload_fileobj(
        fileobj=upload.file,
        object_key=object_key,
        content_type=upload.content_type or "image/png",
    )
    # 头像直接存可访问的预签名 URL(长有效期);后续如需永久化可改为读时签发
    user.avatar_url = storage.presigned_get_url(object_key=object_key, expires_in=7 * 24 * 3600)
    user.save(update_fields=["avatar_url"])
    return Response(UserSerializer(user).data)


def normalize_member_role(role):
    if role == "super":
        return TeamMember.Role.OWNER
    if role in {TeamMember.Role.OWNER, TeamMember.Role.ADMIN, TeamMember.Role.MEMBER, TeamMember.Role.VIEWER}:
        return role
    return TeamMember.Role.MEMBER


def can_manage_team(user, team):
    member = TeamMember.objects.filter(team=team, user=user, status=TeamMember.Status.ACTIVE).first()
    return bool(member and member.role in {TeamMember.Role.OWNER, TeamMember.Role.ADMIN})


@api_view(["GET", "POST"])
@permission_classes([IsAuthenticated])
def team_members(request):
    team = get_current_team(request.user)
    if request.method == "GET":
        members = TeamMember.objects.filter(team=team).select_related("user").order_by("created_at")
        return Response(TeamMemberSerializer(members, many=True).data)

    if not can_manage_team(request.user, team):
        return Response({"detail": "permission denied"}, status=status.HTTP_403_FORBIDDEN)

    username = str(request.data.get("username") or "").strip()
    password = str(request.data.get("password") or "").strip()
    if not username:
        return Response({"username": ["This field is required."]}, status=status.HTTP_400_BAD_REQUEST)
    if len(password) < 8:
        return Response({"password": ["Ensure this field has at least 8 characters."]}, status=status.HTTP_400_BAD_REQUEST)
    if User.objects.filter(username=username).exists():
        return Response({"username": ["username already exists"]}, status=status.HTTP_400_BAD_REQUEST)
    email = str(request.data.get("email") or "").strip() or f"{username}@airshelf.local"
    role = normalize_member_role(request.data.get("role"))
    if role == TeamMember.Role.OWNER:
        role = TeamMember.Role.ADMIN
    with transaction.atomic():
        user = User.objects.create_user(username=username, password=password, email=email)
        user.first_name = str(request.data.get("name") or "").strip()
        user.save(update_fields=["first_name"])
        member = TeamMember.objects.create(
            team=team,
            user=user,
            role=role,
            monthly_credit_limit=request.data.get("monthly_credit_limit") or request.data.get("monthly") or 0,
        )
    return Response(TeamMemberSerializer(member).data, status=status.HTTP_201_CREATED)


@api_view(["PATCH", "DELETE"])
@permission_classes([IsAuthenticated])
def team_member_detail(request, member_id):
    team = get_current_team(request.user)
    if not can_manage_team(request.user, team):
        return Response({"detail": "permission denied"}, status=status.HTTP_403_FORBIDDEN)
    member = TeamMember.objects.select_related("user").filter(team=team, id=member_id).first()
    if member is None:
        return Response({"detail": "not found"}, status=status.HTTP_404_NOT_FOUND)
    if member.user_id == team.owner_id:
        return Response({"detail": "team owner cannot be changed"}, status=status.HTTP_400_BAD_REQUEST)
    if request.method == "DELETE":
        user = member.user
        member.delete()
        if not TeamMember.objects.filter(user=user).exists():
            user.status = User.Status.DISABLED
            user.save(update_fields=["status"])
            Token.objects.filter(user=user).delete()
        return Response(status=status.HTTP_204_NO_CONTENT)

    role = request.data.get("role")
    if role:
        member.role = normalize_member_role(role)
        if member.role == TeamMember.Role.OWNER:
            member.role = TeamMember.Role.ADMIN
    if "monthly_credit_limit" in request.data or "monthly" in request.data:
        member.monthly_credit_limit = request.data.get("monthly_credit_limit", request.data.get("monthly")) or 0
    name = str(request.data.get("name") or "").strip()
    if name:
        member.user.first_name = name
        member.user.save(update_fields=["first_name"])
    member.save(update_fields=["role", "monthly_credit_limit", "updated_at"])
    return Response(TeamMemberSerializer(member).data)


@api_view(["POST"])
@permission_classes([IsAuthenticated])
def team_member_password(request, member_id):
    team = get_current_team(request.user)
    if not can_manage_team(request.user, team):
        return Response({"detail": "permission denied"}, status=status.HTTP_403_FORBIDDEN)
    member = TeamMember.objects.select_related("user").filter(team=team, id=member_id).first()
    if member is None:
        return Response({"detail": "not found"}, status=status.HTTP_404_NOT_FOUND)
    if member.user_id == team.owner_id:
        return Response({"detail": "team owner password cannot be reset here"}, status=status.HTTP_400_BAD_REQUEST)
    password = str(request.data.get("password") or "").strip()
    if len(password) < 8:
        return Response({"password": ["Ensure this field has at least 8 characters."]}, status=status.HTTP_400_BAD_REQUEST)
    member.user.set_password(password)
    member.user.save(update_fields=["password"])
    Token.objects.filter(user=member.user).delete()
    return Response(status=status.HTTP_204_NO_CONTENT)
