"""
Account Management Views for ThrillWiki API v1.

Handles email changes, account deletion, and session management.
"""

import logging
from django.contrib.auth import get_user_model
from django.core.cache import cache
from django.utils import timezone
from drf_spectacular.utils import extend_schema, extend_schema_view
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 rest_framework.views import APIView

logger = logging.getLogger(__name__)
UserModel = get_user_model()


# ============== EMAIL CHANGE ENDPOINTS ==============

@extend_schema(
    operation_id="request_email_change",
    summary="Request email change",
    description="Initiates an email change request. Sends verification to new email.",
    request={
        "application/json": {
            "type": "object",
            "properties": {
                "new_email": {"type": "string", "format": "email"},
                "password": {"type": "string", "description": "Current password for verification"},
            },
            "required": ["new_email", "password"],
        }
    },
    responses={
        200: {"description": "Email change requested"},
        400: {"description": "Invalid request"},
    },
    tags=["Account"],
)
@api_view(["POST"])
@permission_classes([IsAuthenticated])
def request_email_change(request):
    """Request to change email address."""
    user = request.user
    new_email = request.data.get("new_email", "").strip().lower()
    password = request.data.get("password", "")

    if not new_email:
        return Response(
            {"detail": "New email is required"},
            status=status.HTTP_400_BAD_REQUEST,
        )

    if not user.check_password(password):
        return Response(
            {"detail": "Invalid password"},
            status=status.HTTP_400_BAD_REQUEST,
        )

    # Check if email already in use
    if UserModel.objects.filter(email=new_email).exclude(pk=user.pk).exists():
        return Response(
            {"detail": "This email is already in use"},
            status=status.HTTP_400_BAD_REQUEST,
        )

    # Store pending email change in cache
    cache_key = f"email_change:{user.pk}"
    cache.set(
        cache_key,
        {
            "new_email": new_email,
            "requested_at": timezone.now().isoformat(),
        },
        timeout=86400,  # 24 hours
    )

    # TODO: Send verification email to new_email
    # For now, just store the pending change

    return Response({
        "detail": "Email change requested. Please check your new email for verification.",
        "new_email": new_email,
    })


@extend_schema(
    operation_id="get_email_change_status",
    summary="Get pending email change status",
    responses={
        200: {
            "description": "Email change status",
            "example": {
                "has_pending_change": True,
                "new_email": "new@example.com",
                "requested_at": "2026-01-06T12:00:00Z",
            },
        },
    },
    tags=["Account"],
)
@api_view(["GET"])
@permission_classes([IsAuthenticated])
def get_email_change_status(request):
    """Get status of pending email change."""
    user = request.user
    cache_key = f"email_change:{user.pk}"
    pending = cache.get(cache_key)

    if not pending:
        return Response({
            "has_pending_change": False,
            "new_email": None,
            "requested_at": None,
        })

    return Response({
        "has_pending_change": True,
        "new_email": pending.get("new_email"),
        "requested_at": pending.get("requested_at"),
    })


@extend_schema(
    operation_id="cancel_email_change",
    summary="Cancel pending email change",
    responses={
        200: {"description": "Email change cancelled"},
    },
    tags=["Account"],
)
@api_view(["POST"])
@permission_classes([IsAuthenticated])
def cancel_email_change(request):
    """Cancel a pending email change request."""
    user = request.user
    cache_key = f"email_change:{user.pk}"
    cache.delete(cache_key)

    return Response({"detail": "Email change cancelled"})


# ============== ACCOUNT DELETION ENDPOINTS ==============

@extend_schema(
    operation_id="request_account_deletion",
    summary="Request account deletion",
    description="Initiates account deletion. Requires password confirmation.",
    request={
        "application/json": {
            "type": "object",
            "properties": {
                "password": {"type": "string"},
                "reason": {"type": "string", "description": "Optional reason for leaving"},
            },
            "required": ["password"],
        }
    },
    responses={
        200: {"description": "Deletion requested"},
        400: {"description": "Invalid password"},
    },
    tags=["Account"],
)
@api_view(["POST"])
@permission_classes([IsAuthenticated])
def request_account_deletion(request):
    """Request account deletion."""
    user = request.user
    password = request.data.get("password", "")
    reason = request.data.get("reason", "")

    if not user.check_password(password):
        return Response(
            {"detail": "Invalid password"},
            status=status.HTTP_400_BAD_REQUEST,
        )

    # Store deletion request in cache (will be processed by background task)
    cache_key = f"account_deletion:{user.pk}"
    deletion_date = timezone.now() + timezone.timedelta(days=30)
    
    cache.set(
        cache_key,
        {
            "requested_at": timezone.now().isoformat(),
            "scheduled_deletion": deletion_date.isoformat(),
            "reason": reason,
        },
        timeout=2592000,  # 30 days
    )

    # Also update user profile if it exists
    try:
        from apps.accounts.models import Profile
        profile = Profile.objects.filter(user=user).first()
        if profile:
            profile.deletion_requested_at = timezone.now()
            profile.scheduled_deletion_date = deletion_date
            profile.save(update_fields=["deletion_requested_at", "scheduled_deletion_date"])
    except Exception as e:
        logger.warning(f"Could not update profile for deletion: {e}")

    return Response({
        "detail": "Account deletion scheduled",
        "scheduled_deletion": deletion_date.isoformat(),
    })


@extend_schema(
    operation_id="get_deletion_status",
    summary="Get account deletion status",
    responses={
        200: {
            "description": "Deletion status",
            "example": {
                "deletion_pending": True,
                "scheduled_deletion": "2026-02-06T12:00:00Z",
            },
        },
    },
    tags=["Account"],
)
@api_view(["GET"])
@permission_classes([IsAuthenticated])
def get_deletion_status(request):
    """Get status of pending account deletion."""
    user = request.user
    cache_key = f"account_deletion:{user.pk}"
    pending = cache.get(cache_key)

    if not pending:
        # Also check profile
        try:
            from apps.accounts.models import Profile
            profile = Profile.objects.filter(user=user).first()
            if profile and profile.deletion_requested_at:
                return Response({
                    "deletion_pending": True,
                    "requested_at": profile.deletion_requested_at.isoformat(),
                    "scheduled_deletion": profile.scheduled_deletion_date.isoformat() if profile.scheduled_deletion_date else None,
                })
        except Exception:
            pass

        return Response({
            "deletion_pending": False,
            "scheduled_deletion": None,
        })

    return Response({
        "deletion_pending": True,
        "requested_at": pending.get("requested_at"),
        "scheduled_deletion": pending.get("scheduled_deletion"),
    })


@extend_schema(
    operation_id="cancel_account_deletion",
    summary="Cancel account deletion",
    responses={
        200: {"description": "Deletion cancelled"},
    },
    tags=["Account"],
)
@api_view(["POST"])
@permission_classes([IsAuthenticated])
def cancel_account_deletion(request):
    """Cancel a pending account deletion request."""
    user = request.user
    cache_key = f"account_deletion:{user.pk}"
    cache.delete(cache_key)

    # Also clear from profile
    try:
        from apps.accounts.models import Profile
        Profile.objects.filter(user=user).update(
            deletion_requested_at=None,
            scheduled_deletion_date=None,
        )
    except Exception as e:
        logger.warning(f"Could not clear deletion from profile: {e}")

    return Response({"detail": "Account deletion cancelled"})


# ============== SESSION MANAGEMENT ENDPOINTS ==============

@extend_schema(
    operation_id="list_sessions",
    summary="List active sessions",
    description="Returns list of active sessions for the current user.",
    responses={
        200: {
            "description": "List of sessions",
            "example": {
                "sessions": [
                    {
                        "id": "session_123",
                        "created_at": "2026-01-06T12:00:00Z",
                        "last_activity": "2026-01-06T14:00:00Z",
                        "ip_address": "192.168.1.1",
                        "user_agent": "Mozilla/5.0...",
                        "is_current": True,
                    }
                ]
            },
        },
    },
    tags=["Account"],
)
@api_view(["GET"])
@permission_classes([IsAuthenticated])
def list_sessions(request):
    """List all active sessions for the user."""
    # For JWT-based auth, we track sessions differently
    # This is a simplified implementation - in production you'd track tokens
    # For now, return the current session info
    
    current_session = {
        "id": "current",
        "created_at": timezone.now().isoformat(),
        "last_activity": timezone.now().isoformat(),
        "ip_address": request.META.get("REMOTE_ADDR", "unknown"),
        "user_agent": request.META.get("HTTP_USER_AGENT", "unknown"),
        "is_current": True,
    }

    return Response({
        "sessions": [current_session],
        "count": 1,
    })


@extend_schema(
    operation_id="revoke_session",
    summary="Revoke a session",
    description="Revokes a specific session. If revoking current session, user will be logged out.",
    responses={
        200: {"description": "Session revoked"},
        404: {"description": "Session not found"},
    },
    tags=["Account"],
)
@api_view(["DELETE"])
@permission_classes([IsAuthenticated])
def revoke_session(request, session_id):
    """Revoke a specific session."""
    # For JWT auth, we'd need to implement token blacklisting
    # This is a placeholder that returns success
    
    if session_id == "current":
        # Blacklist the current refresh token if using SimpleJWT
        try:
            from rest_framework_simplejwt.token_blacklist.models import BlacklistedToken
            from rest_framework_simplejwt.tokens import RefreshToken
            
            # Get refresh token from request if available
            refresh_token = request.data.get("refresh_token")
            if refresh_token:
                token = RefreshToken(refresh_token)
                token.blacklist()
        except Exception as e:
            logger.warning(f"Could not blacklist token: {e}")

    return Response({"detail": "Session revoked"})


# ============== PASSWORD CHANGE ENDPOINT ==============

@extend_schema(
    operation_id="change_password",
    summary="Change password",
    description="Changes the user's password. Requires current password.",
    request={
        "application/json": {
            "type": "object",
            "properties": {
                "current_password": {"type": "string"},
                "new_password": {"type": "string"},
            },
            "required": ["current_password", "new_password"],
        }
    },
    responses={
        200: {"description": "Password changed"},
        400: {"description": "Invalid current password or weak new password"},
    },
    tags=["Account"],
)
@api_view(["POST"])
@permission_classes([IsAuthenticated])
def change_password(request):
    """Change user password."""
    user = request.user
    current_password = request.data.get("current_password", "")
    new_password = request.data.get("new_password", "")

    if not user.check_password(current_password):
        return Response(
            {"detail": "Current password is incorrect"},
            status=status.HTTP_400_BAD_REQUEST,
        )

    if len(new_password) < 8:
        return Response(
            {"detail": "New password must be at least 8 characters"},
            status=status.HTTP_400_BAD_REQUEST,
        )

    user.set_password(new_password)
    user.save()

    return Response({"detail": "Password changed successfully"})
