""" Account Management API Views Handles account settings, team management, and usage analytics """ from rest_framework import viewsets, status from rest_framework.decorators import action from rest_framework.response import Response from rest_framework.permissions import IsAuthenticated from django.contrib.auth import get_user_model from django.db.models import Q, Count, Sum from django.utils import timezone from datetime import timedelta from drf_spectacular.utils import extend_schema, extend_schema_view from igny8_core.auth.models import Account from igny8_core.business.billing.models import CreditTransaction User = get_user_model() @extend_schema_view( retrieve=extend_schema(tags=['Account']), partial_update=extend_schema(tags=['Account']), ) class AccountSettingsViewSet(viewsets.ViewSet): """Account settings management""" permission_classes = [IsAuthenticated] def retrieve(self, request): """Get account settings""" account = request.user.account return Response({ 'id': account.id, 'name': account.name, 'slug': account.slug, 'billing_address_line1': account.billing_address_line1 or '', 'billing_address_line2': account.billing_address_line2 or '', 'billing_city': account.billing_city or '', 'billing_state': account.billing_state or '', 'billing_postal_code': account.billing_postal_code or '', 'billing_country': account.billing_country or '', 'tax_id': account.tax_id or '', 'billing_email': account.billing_email or '', 'credits': account.credits, 'created_at': account.created_at.isoformat(), 'updated_at': account.updated_at.isoformat(), }) def partial_update(self, request): """Update account settings""" account = request.user.account # Update allowed fields allowed_fields = [ 'name', 'billing_address_line1', 'billing_address_line2', 'billing_city', 'billing_state', 'billing_postal_code', 'billing_country', 'tax_id', 'billing_email' ] for field in allowed_fields: if field in request.data: setattr(account, field, request.data[field]) account.save() return Response({ 'message': 'Account settings updated successfully', 'account': { 'id': account.id, 'name': account.name, 'slug': account.slug, 'billing_address_line1': account.billing_address_line1, 'billing_address_line2': account.billing_address_line2, 'billing_city': account.billing_city, 'billing_state': account.billing_state, 'billing_postal_code': account.billing_postal_code, 'billing_country': account.billing_country, 'tax_id': account.tax_id, 'billing_email': account.billing_email, } }) @extend_schema_view( list=extend_schema(tags=['Account']), create=extend_schema(tags=['Account']), destroy=extend_schema(tags=['Account']), ) class TeamManagementViewSet(viewsets.ViewSet): """Team members management""" permission_classes = [IsAuthenticated] def list(self, request): """List team members""" account = request.user.account users = User.objects.filter(account=account) return Response({ 'results': [ { 'id': user.id, 'email': user.email, 'first_name': user.first_name, 'last_name': user.last_name, 'is_active': user.is_active, 'is_staff': user.is_staff, 'date_joined': user.date_joined.isoformat(), 'last_login': user.last_login.isoformat() if user.last_login else None, } for user in users ], 'count': users.count() }) def create(self, request): """Invite new team member""" account = request.user.account email = request.data.get('email') if not email: return Response( {'error': 'Email is required'}, status=status.HTTP_400_BAD_REQUEST ) # Check if user already exists if User.objects.filter(email=email).exists(): return Response( {'error': 'User with this email already exists'}, status=status.HTTP_400_BAD_REQUEST ) # Create user (simplified - in production, send invitation email) user = User.objects.create_user( email=email, first_name=request.data.get('first_name', ''), last_name=request.data.get('last_name', ''), account=account ) return Response({ 'message': 'Team member invited successfully', 'user': { 'id': user.id, 'email': user.email, 'first_name': user.first_name, 'last_name': user.last_name, } }, status=status.HTTP_201_CREATED) def destroy(self, request, pk=None): """Remove team member""" account = request.user.account try: user = User.objects.get(id=pk, account=account) # Prevent removing yourself if user.id == request.user.id: return Response( {'error': 'Cannot remove yourself'}, status=status.HTTP_400_BAD_REQUEST ) user.is_active = False user.save() return Response({ 'message': 'Team member removed successfully' }) except User.DoesNotExist: return Response( {'error': 'User not found'}, status=status.HTTP_404_NOT_FOUND ) @extend_schema_view( overview=extend_schema(tags=['Account']), ) class UsageAnalyticsViewSet(viewsets.ViewSet): """Usage analytics and statistics""" permission_classes = [IsAuthenticated] @action(detail=False, methods=['get']) def overview(self, request): """Get usage analytics overview""" account = request.user.account # Get date range (default: last 30 days) days = int(request.query_params.get('days', 30)) start_date = timezone.now() - timedelta(days=days) # Get transactions in period transactions = CreditTransaction.objects.filter( account=account, created_at__gte=start_date ) # Calculate totals by type usage_by_type = transactions.filter( amount__lt=0 ).values('transaction_type').annotate( total=Sum('amount'), count=Count('id') ) purchases_by_type = transactions.filter( amount__gt=0 ).values('transaction_type').annotate( total=Sum('amount'), count=Count('id') ) # Daily usage daily_usage = [] for i in range(days): date = start_date + timedelta(days=i) day_txns = transactions.filter( created_at__date=date.date() ) usage = day_txns.filter(amount__lt=0).aggregate(Sum('amount'))['amount__sum'] or 0 purchases = day_txns.filter(amount__gt=0).aggregate(Sum('amount'))['amount__sum'] or 0 daily_usage.append({ 'date': date.date().isoformat(), 'usage': abs(usage), 'purchases': purchases, 'net': purchases + usage }) return Response({ 'period_days': days, 'start_date': start_date.isoformat(), 'end_date': timezone.now().isoformat(), 'current_balance': account.credits, 'usage_by_type': list(usage_by_type), 'purchases_by_type': list(purchases_by_type), 'daily_usage': daily_usage, 'total_usage': abs(transactions.filter(amount__lt=0).aggregate(Sum('amount'))['amount__sum'] or 0), 'total_purchases': transactions.filter(amount__gt=0).aggregate(Sum('amount'))['amount__sum'] or 0, })