from decimal import Decimal, InvalidOperation

from django.db import transaction
from django.db.models import Sum
from rest_framework import status
from rest_framework.decorators import api_view, permission_classes
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response

from apps.common.api import get_current_team

from .models import CreditAccount, CreditLedger
from .serializers import CreditAccountSerializer, CreditLedgerSerializer


@api_view(["GET"])
@permission_classes([IsAuthenticated])
def summary(request):
    team = get_current_team(request.user)
    account, _ = CreditAccount.objects.get_or_create(team=team)
    charged = CreditLedger.objects.filter(team=team, ledger_type=CreditLedger.Type.CHARGE).aggregate(
        total=Sum("amount")
    )["total"] or 0
    return Response(
        {
            "account": CreditAccountSerializer(account).data,
            "charged_total": charged,
        }
    )


@api_view(["GET"])
@permission_classes([IsAuthenticated])
def ledgers(request):
    team = get_current_team(request.user)
    queryset = CreditLedger.objects.filter(team=team).select_related("user", "project", "task").order_by("-created_at")
    project_id = request.query_params.get("project")
    user_id = request.query_params.get("user")
    if project_id:
        queryset = queryset.filter(project_id=project_id)
    if user_id:
        queryset = queryset.filter(user_id=user_id)
    return Response(CreditLedgerSerializer(queryset[:100], many=True).data)


@api_view(["POST"])
@permission_classes([IsAuthenticated])
def recharge(request):
    team = get_current_team(request.user)
    try:
        amount = Decimal(str(request.data.get("amount", "0")))
        bonus = Decimal(str(request.data.get("bonus", "0")))
    except (InvalidOperation, TypeError):
        return Response({"detail": "invalid amount"}, status=status.HTTP_400_BAD_REQUEST)
    if amount <= 0:
        return Response({"detail": "amount must be positive"}, status=status.HTTP_400_BAD_REQUEST)
    if bonus < 0:
        return Response({"detail": "bonus cannot be negative"}, status=status.HTTP_400_BAD_REQUEST)
    channel = str(request.data.get("channel") or "manual")[:32]
    credited = amount + bonus
    with transaction.atomic():
        account, _ = CreditAccount.objects.select_for_update().get_or_create(team=team)
        account.balance += credited
        account.save(update_fields=["balance", "updated_at"])
        ledger = CreditLedger.objects.create(
            team=team,
            user=request.user,
            ledger_type=CreditLedger.Type.RECHARGE,
            amount=credited,
            balance_after=account.balance,
            reason="团队充值",
            metadata={"channel": channel, "paid_amount": str(amount), "bonus": str(bonus)},
        )
    return Response(
        {
            "account": CreditAccountSerializer(account).data,
            "ledger": CreditLedgerSerializer(ledger).data,
        },
        status=status.HTTP_201_CREATED,
    )
