"""Anonymize accounts only after their sporting and financial obligations end."""
import uuid
from datetime import timedelta
from django.db import transaction
from django.db.models import Q
from django.utils import timezone
from rest_framework.exceptions import ValidationError
from core_runtime.models import OutboxEvent
from .models import User, AccountEmail
from .security_models import AccountDeletionRequest, AccountSession, AccountSecurity, LoginIdentity, PasskeyCredential, AuthChallenge
from .security_sessions import revoke_all


@transaction.atomic
def request_deletion(user,reason=''):
    user=User.objects.select_for_update().get(pk=user.pk)
    if not user.is_active:
        raise ValidationError('The account is inactive.')
    request,created=AccountDeletionRequest.objects.get_or_create(user=user,status='PENDING',
        defaults={'reason':reason,'eligible_after':timezone.now()+timedelta(days=30)})
    if created:
        OutboxEvent.objects.create(topic='users',event_type='account.deletion.requested',aggregate_type='User',
            aggregate_id=str(user.pk),payload={'request_id':str(request.pk)})
        AccountEmail.objects.create(recipient=user.email,subject='FTG: account deletion requested',
            body='Your deletion request was recorded. Sign in to cancel it within 30 days. Contracts, assets and financial obligations must be resolved before anonymization.',
            expires_at=timezone.now()+timedelta(days=2),next_attempt_at=timezone.now())
    user.auth_version=uuid.uuid4();user.save(update_fields=['auth_version','updated_at']);revoke_all(user)
    return {'id':str(request.pk),'status':request.status,'eligible_after':request.eligible_after.isoformat(),'signed_out':True}


def blockers(user):
    from careers.models import Career
    from club_ownership.models import ClubOwnership
    from clubs.models import Club
    from economy.models import Wallet
    from federations.models import FederationAdminAssignment
    from asset_registry.models import AssetRecord
    reasons=[]
    if user.is_superuser or user.is_staff:
        reasons.append('Remove platform administration authority first.')
    if Career.objects.filter(user=user,status='ACTIVE').exists():
        reasons.append('Active sporting careers must be completed through their domain services.')
    if ClubOwnership.objects.filter(owner=user).exists() or Club.objects.filter(coach_career__user=user,status='ACTIVE').exists():
        reasons.append('Club ownership and management obligations remain.')
    if FederationAdminAssignment.objects.filter(user=user,is_active=True).exists():
        reasons.append('Active federation appointments remain.')
    if AssetRecord.objects.filter(owner_user=user).exists():
        reasons.append('Registered assets must be transferred through their domain services first.')
    # Include player wallets belonging to every career, not just the active one.
    if Wallet.objects.filter(Q(account=user)|Q(player__career__user=user)).exclude(available_balance=0,reserved_balance=0).exists():
        reasons.append('A wallet still holds available or reserved funds.')
    if Wallet.objects.filter(account=user).exists():
        reasons.append('An existing financial account requires a domain review, including pending deposits and withdrawals.')
    # A sporting history may contain open contracts or player-owned assets even
    # after its career was closed. These accounts require a manual domain review.
    if user.careers.exists():
        reasons.append('Sporting history requires a domain review; automatic anonymization is restricted to accounts without careers.')
    return reasons


@transaction.atomic
def finalize(request_id):
    # Lock the user first, consistent with all account/credential mutations.
    identity=AccountDeletionRequest.objects.get(pk=request_id)
    user=User.objects.select_for_update().get(pk=identity.user_id)
    row=AccountDeletionRequest.objects.select_for_update().get(pk=request_id)
    if row.status!='PENDING' or row.eligible_after>timezone.now():
        raise ValidationError('Request is not pending or the cancellation period has not elapsed.')
    reasons=blockers(user)
    if reasons:
        raise ValidationError(reasons)
    original_email=user.email
    user.email=f'deleted.{user.pk.hex}@accounts.invalid';user.username=f'deleted_{user.pk.hex}'
    user.first_name=user.last_name=user.display_name='';user.is_active=False;user.is_email_verified=False
    user.auth_version=uuid.uuid4();user.set_unusable_password();user.save()
    revoke_all(user)
    AccountSession.objects.filter(user=user).update(user_agent='',ip_address=None)
    AccountSecurity.objects.filter(user=user).delete();LoginIdentity.objects.filter(user=user).delete()
    PasskeyCredential.objects.filter(user=user).delete();AuthChallenge.objects.filter(user=user).delete()
    AccountEmail.objects.filter(recipient__iexact=original_email).delete()
    row.reason='';row.status='COMPLETED';row.resolved_at=timezone.now();row.save()
    OutboxEvent.objects.create(topic='users',event_type='account.anonymized',aggregate_type='User',
        aggregate_id=str(user.pk),payload={'request_id':str(row.pk)})
    return {'id':str(row.pk),'status':row.status}
