from django.shortcuts import render, redirect
from django.contrib.auth.decorators import login_required
from django.contrib import messages
from django.contrib.auth import login, authenticate, logout, get_user_model
from django.contrib.auth.views import LogoutView
from django.contrib.auth.forms import AuthenticationForm
from django.db import transaction
from django.core.mail import send_mail
from django.template.loader import render_to_string
from django.conf import settings
from django.utils import timezone
from django.utils.http import urlsafe_base64_encode, urlsafe_base64_decode
from django.utils.encoding import force_bytes
from datetime import timedelta, datetime
from django.urls import reverse
from django.utils.html import strip_tags
from django.http import JsonResponse

from .forms import (UserForm, ProfileForm, UserRegistrationForm, AccountDeletionForm, 
                   PublicAccountDeletionForm, QuickRegistrationForm, TemporaryUserRegistrationForm,
                   PhoneAuthenticationForm)
from .models import UserProfile, AccountDeletionRequest, DeletedUser, DeletedUserProfile
from .utils import transfer_user_data, cleanup_temp_user
import logging

logger = logging.getLogger(__name__)

User = get_user_model()

def register(request):
    """Handle user registration."""
    # Redirect temporary users to temp-register page
    if (request.user.is_authenticated and 
        hasattr(request.user, 'is_temporary_user') and 
        request.user.is_temporary_user):
        return redirect('accounts:temp_register')
    
    if request.method == 'POST':
        form = UserRegistrationForm(request.POST)
        if form.is_valid():
            user = form.save()
            # Log the user in
            phone = form.cleaned_data['phone']
            password = form.cleaned_data['password1']
            user = authenticate(request, phone=phone, password=password)
            if user is not None:
                login(request, user)
                messages.success(request, '注册成功！')
                # Redirect to next page if specified, otherwise to home
                next_page = request.GET.get('next', 'main:index')
                return redirect(next_page)
    else:
        form = UserRegistrationForm()
    
    return render(request, 'accounts/register.html', {'form': form})

@login_required
def profile_view(request):
    """Display user profile information."""
    return render(request, 'accounts/profile_view.html', {
        'user': request.user,
        'profile': request.user.profile
    })

@login_required
@transaction.atomic
def profile_edit(request):
    """Edit user profile information."""
    # Redirect temporary users to registration page
    if hasattr(request.user, 'is_temporary_user') and request.user.is_temporary_user:
        return redirect('accounts:temp_register')
    
    if request.method == 'POST':
        user_form = UserForm(request.POST, instance=request.user)
        profile_form = ProfileForm(request.POST, instance=request.user.profile)
        
        if user_form.is_valid() and profile_form.is_valid():
            user_form.save()
            profile_form.save()
            messages.success(request, '个人资料更新成功！')
            return redirect('accounts:profile_view')
        else:
            messages.error(request, '请修正下列错误。')
    else:
        user_form = UserForm(instance=request.user)
        profile_form = ProfileForm(instance=request.user.profile)
    
    return render(request, 'accounts/profile_edit.html', {
        'user_form': user_form,
        'profile_form': profile_form
    })

@login_required
def request_account_deletion(request):
    if request.method == 'POST':
        form = AccountDeletionForm(user=request.user, data=request.POST)
        if form.is_valid():
            # Create deletion request
            expires_at = timezone.now() + timedelta(hours=24)
            deletion_request = AccountDeletionRequest.objects.create(
                user=request.user,
                expires_at=expires_at,
                is_active=True,
                contact_email=request.user.email,
                contact_phone=request.user.phone,
                reason=form.cleaned_data.get('reason', '')
            )
            
            # Generate confirmation URL
            confirmation_url = request.build_absolute_uri(
                reverse('accounts:confirm_deletion', kwargs={'token': deletion_request.token})
            )
            
            # Determine user's email
            email = request.user.email or request.user.phone
            
            # Prepare and send email
            context = {
                'user': request.user,
                'confirmation_url': confirmation_url,
                'current_year': timezone.now().year,
                'site_title': getattr(settings, 'SITE_TITLE', '易经'),
            }
            
            html_message = render_to_string('accounts/emails/account_deletion_confirmation.html', context)
            subject = '确认删除您的账户'
            send_mail(
                subject=subject,
                message=strip_tags(html_message),
                from_email=settings.DEFAULT_FROM_EMAIL,
                recipient_list=[email],
                html_message=html_message,
                fail_silently=False,
            )
            
            return redirect('accounts:deletion_email_sent', email=email)
    else:
        form = AccountDeletionForm(user=request.user)
    
    return render(request, 'accounts/delete_account.html', {'form': form})

@login_required
def deletion_email_sent(request, email):
    return render(request, 'accounts/deletion_email_sent.html', {'email': email})

def confirm_account_deletion(request, token):
    try:
        deletion_request = AccountDeletionRequest.objects.get(token=token, is_active=True)
        
        # Check if token is expired
        if deletion_request.expires_at < timezone.now():
            messages.error(request, '删除确认链接已过期。请重新提交删除请求。')
            return redirect('accounts:profile_view')
        
        # If it's a POST request, process the deletion
        if request.method == 'POST':
            user = deletion_request.user
            
            # Get contact information from deletion request
            contact_email = deletion_request.contact_email or None
            
            # Store user data before deletion
            deleted_user = DeletedUser.objects.create(
                original_id=user.id,
                phone=user.phone,
                email=user.email,
                first_name=user.first_name,
                last_name=user.last_name,
                date_joined=user.date_joined,
                reason=deletion_request.reason
            )
            
            # Try to store profile data if exists
            try:
                profile = user.profile
                # Serialize the profile details into a dictionary
                profile_data = {
                    "birth_date": profile.birth_date.strftime("%Y-%m-%d") if profile.birth_date else None,
                }
                DeletedUserProfile.objects.create(
                    deleted_user=deleted_user,
                    original_id=profile.id,
                    created_at=profile.created_at,
                    profile_data=profile_data,
                )
            except UserProfile.DoesNotExist:
                pass

            # Store original user ID in Bazi records
            from bazi.models import Person
            Person.objects.filter(created_by=user).update(
                ori_user=user.id,
                created_by=None
            )

            # Store original user ID in Liuyao records
            from liuyao.models import liuyao
            liuyao.objects.filter(user=user).update(
                ori_user=user.id,
                user=None
            )
            
            # Deactivate the deletion request
            deletion_request.is_active = False
            deletion_request.save()
            
            # Logout the user
            if request.user.is_authenticated and request.user == user:
                logout(request)
            
            # Delete the user
            user.delete()
            
            # Send deletion confirmation email
            if contact_email is not None:
                context = {
                    'current_year': timezone.now().year,
                    'site_title': getattr(settings, 'SITE_TITLE', '易经'),
                }
                
                html_message = render_to_string('accounts/emails/account_deleted_confirmation.html', context)
                subject = '您的账户已成功删除'
                
                send_mail(
                    subject=subject,
                    message=strip_tags(html_message),
                    from_email=settings.DEFAULT_FROM_EMAIL,
                    recipient_list=[contact_email],
                    html_message=html_message,
                    fail_silently=False,
                )
            
            return render(request, 'accounts/account_deleted.html')
        
        # For GET request, show the confirmation page
        return render(request, 'accounts/confirm_deletion.html', {
            'deletion_request': deletion_request
        })
        
    except AccountDeletionRequest.DoesNotExist:
        messages.error(request, '无效的删除确认链接。')
        return redirect('accounts:profile_view')

def public_request_account_deletion(request):
    """Handle public account deletion requests."""
    if request.method == 'POST':
        form = PublicAccountDeletionForm(request.POST)
        if form.is_valid():
            phone = form.cleaned_data['phone']
            email = form.cleaned_data['email']
            reason = form.cleaned_data.get('reason')

            try:
                user = User.objects.get(phone=phone, email=email)
                
                # Create deletion request
                expires_at = timezone.now() + timedelta(hours=24)
                deletion_request = AccountDeletionRequest.objects.create(
                    user=user,
                    expires_at=expires_at,
                    is_active=True,
                    contact_email=email,
                    contact_phone=phone,
                    reason=reason
                )
                
                # Generate confirmation URL
                confirmation_url = request.build_absolute_uri(
                    reverse('accounts:confirm_deletion', kwargs={'token': deletion_request.token})
                )
                
                # Prepare and send email
                context = {
                    'user': user,
                    'confirmation_url': confirmation_url,
                    'current_year': timezone.now().year,
                    'site_title': getattr(settings, 'SITE_TITLE', '易经'),
                }
                
                html_message = render_to_string('accounts/emails/account_deletion_confirmation.html', context)
                subject = '确认删除您的账户'
                send_mail(
                    subject=subject,
                    message=strip_tags(html_message),
                    from_email=settings.DEFAULT_FROM_EMAIL,
                    recipient_list=[email],
                    html_message=html_message,
                    fail_silently=False,
                )
            except User.DoesNotExist:
                # We don't want to reveal if the account exists or not
                pass

            # Always redirect to the confirmation page
            return redirect('main:public_deletion_request_sent')
    else:
        form = PublicAccountDeletionForm()
    
    return render(request, 'accounts/public_delete_account.html', {'form': form})

def public_deletion_request_sent(request):
    """Show confirmation message for public deletion request."""
    return render(request, 'accounts/public_deletion_request_sent.html')

def quick_register(request):
    """Handle quick registration from number power results."""
    # Redirect temporary users to temp-register page
    if (request.user.is_authenticated and 
        hasattr(request.user, 'is_temporary_user') and 
        request.user.is_temporary_user):
        return redirect('accounts:temp_register')
    
    if request.method == 'POST':
        form = QuickRegistrationForm(request.POST)
        if form.is_valid():
            # Extract form data
            phone = form.cleaned_data['phone']
            email = form.cleaned_data['email']
            password = form.cleaned_data['password']
            
            # Log the data for debugging
            print(f"Form data: {form.cleaned_data}")
            
            # Create user
            user = User.objects.create_user(
                phone=phone, 
                email=email, 
                password=password
            )
            
            # Add name as first_name if provided
            if form.cleaned_data.get('name'):
                user.first_name = form.cleaned_data['name']
                user.save()
                
            # Add gender if provided
            if form.cleaned_data.get('gender'):
                user.gender = form.cleaned_data['gender']
                user.save()
                
            # Get or create profile
            profile, created = UserProfile.objects.get_or_create(user=user)
            
            # Update profile with form data
            if form.cleaned_data.get('birth_date'):
                birth_date_str = form.cleaned_data['birth_date']
                # Remove any Chinese characters 
                birth_date_str = birth_date_str.replace('年', '-').replace('月', '-').replace('日', '')
                
                try:
                    # Try standard format first
                    profile.birth_date = datetime.strptime(birth_date_str, '%Y-%m-%d').date()
                except ValueError:
                    try:
                        # Try without dashes
                        profile.birth_date = datetime.strptime(birth_date_str, '%Y%m%d').date()
                    except ValueError:
                        print(f"Failed to parse birth date: {birth_date_str}")
                    
            if form.cleaned_data.get('birth_time'):
                try:
                    profile.birth_time = datetime.strptime(form.cleaned_data['birth_time'], '%H:%M').time()
                except (ValueError, TypeError):
                    print(f"Failed to parse birth time: {form.cleaned_data['birth_time']}")
                    
            if form.cleaned_data.get('twin_type'):
                try:
                    profile.twin_type = int(form.cleaned_data['twin_type'])
                except (ValueError, TypeError):
                    print(f"Failed to parse twin type: {form.cleaned_data['twin_type']}")
                    
            if form.cleaned_data.get('father_dob'):
                father_dob_str = form.cleaned_data['father_dob']
                # Remove any Chinese characters 
                father_dob_str = father_dob_str.replace('年', '-').replace('月', '-').replace('日', '')
                
                try:
                    # Try standard format first
                    profile.father_dob = datetime.strptime(father_dob_str, '%Y-%m-%d').date()
                except ValueError:
                    try:
                        # Try without dashes
                        profile.father_dob = datetime.strptime(father_dob_str, '%Y%m%d').date()
                    except ValueError:
                        print(f"Failed to parse father DOB: {father_dob_str}")
                    
            if form.cleaned_data.get('mother_dob'):
                mother_dob_str = form.cleaned_data['mother_dob']
                # Remove any Chinese characters 
                mother_dob_str = mother_dob_str.replace('年', '-').replace('月', '-').replace('日', '')
                
                try:
                    # Try standard format first
                    profile.mother_dob = datetime.strptime(mother_dob_str, '%Y-%m-%d').date()
                except ValueError:
                    try:
                        # Try without dashes
                        profile.mother_dob = datetime.strptime(mother_dob_str, '%Y%m%d').date()
                    except ValueError:
                        print(f"Failed to parse mother DOB: {mother_dob_str}")
            
            # Save the profile - this will trigger the signal handler to create the BaZi record
            profile.save()
            
            # Note: We don't need to create a BaZi record manually as it's created by the signal handler
            
            # Log the user in
            user = authenticate(request, phone=phone, password=password)
            if user is not None:
                login(request, user)
                messages.success(request, '注册成功！您的数字能量图已保存。')
                
                # Determine redirect URL based on referer
                referer = request.META.get('HTTP_REFERER', '')
                if 'bazi' in referer:
                    redirect_url = reverse('bazi:person_list')
                elif 'liuyao' in referer:
                    redirect_url = reverse('liuyao:list')
                else:
                    redirect_url = reverse('number:charts')
                
                # If it's an AJAX request, return JSON response
                if request.headers.get('X-Requested-With') == 'XMLHttpRequest':
                    return JsonResponse({'success': True, 'redirect': redirect_url})
                
                # Redirect to appropriate page
                return redirect(redirect_url)
            else:
                messages.success(request, '注册成功！请登录继续。')
                
                # If it's an AJAX request, return JSON response
                if request.headers.get('X-Requested-With') == 'XMLHttpRequest':
                    return JsonResponse({'success': True, 'redirect': reverse('accounts:login')})
                
                return redirect('accounts:login')
        else:
            # If it's an AJAX request, return form errors as JSON
            if request.headers.get('X-Requested-With') == 'XMLHttpRequest':
                return JsonResponse({'success': False, 'errors': form.errors.as_json()})
            
    else:
        # For GET requests, create an empty form
        form = QuickRegistrationForm()
    
    # Render the form for non-AJAX GET requests
    return render(request, 'accounts/quick_register.html', {'form': form})


# Temporary User Views

def temp_user_register(request):
    """
    Handle temporary user registration to permanent account.
    """
    # Only allow temporary users
    if not (request.user.is_authenticated and 
            hasattr(request.user, 'is_temporary_user') and 
            request.user.is_temporary_user):
        messages.error(request, '此页面仅限临时用户访问。')
        return redirect('main:index')
    
    if request.method == 'POST':
        form = TemporaryUserRegistrationForm(temp_user=request.user, data=request.POST)
        if form.is_valid():
            try:
                # Convert temporary user to permanent user
                permanent_user = form.save(request.user)
                
                # Re-authenticate with the updated user
                login(request, permanent_user)
                
                messages.success(request, '账户注册成功！您的数据已保存。')
                return redirect('main:index')
            except Exception as e:
                logger.error(f"Error converting temp user {request.user.id} to permanent: {e}")
                messages.error(request, f'注册过程中发生错误：{str(e)}')
        else:
            # Add form error messages
            for field, errors in form.errors.items():
                for error in errors:
                    field_label = getattr(form.fields.get(field), 'label', field) if form.fields.get(field) else field
                    messages.error(request, f'{field_label}: {error}')
    else:
        form = TemporaryUserRegistrationForm(temp_user=request.user)
    
    return render(request, 'accounts/temp_user_register.html', {
        'form': form,
        'user': request.user
    })


class CustomLogoutView(LogoutView):
    """Custom logout view that handles both regular and temporary users."""
    
    def dispatch(self, request, *args, **kwargs):
        # Check if user is temporary before logout
        if (request.user.is_authenticated and 
            hasattr(request.user, 'is_temporary_user') and 
            request.user.is_temporary_user):
            # For temp users, clear the session but show different message
            messages.info(request, '临时用户数据已清除。')
            # Note: JWT tokens will be cleared by JavaScript clearTempUserTokens()
        
        # For all users (including temp users), proceed with normal logout
        return super().dispatch(request, *args, **kwargs)


@transaction.atomic
def enhanced_login(request):
    """
    Enhanced login view that handles data transfer for temporary users.
    """
    temp_user = None
    is_temp_user = False
    
    # Check if current user is temporary
    if request.user.is_authenticated and getattr(request.user, 'is_temporary_user', False):
        temp_user = request.user
        is_temp_user = True
    
    if request.method == 'POST':
        form = PhoneAuthenticationForm(request, data=request.POST)
        if form.is_valid():
            target_user = form.get_user()
            
            # Transfer data if logging in from a temporary user
            if temp_user and temp_user.is_temporary_user:
                try:
                    summary = transfer_user_data(temp_user, target_user)
                    cleanup_temp_user(temp_user)
                    
                    # Show success message with transfer summary
                    if summary['bazi_records'] > 0 or summary['liuyao_records'] > 0:
                        message = f"登录成功！已转移 {summary['bazi_records']} 个八字记录和 {summary['liuyao_records']} 个六爻记录到您的账户。"
                        if summary['owner_flag_cleared']:
                            message += " 注意：由于您已有主命盘，转移的记录已调整为非主命盘。"
                        messages.success(request, message)
                    else:
                        messages.success(request, '登录成功！')
                except Exception as e:
                    logger.error(f"Error transferring data from temp user {temp_user.id} to {target_user.id}: {e}")
                    messages.warning(request, '数据转移时发生错误，请联系客服。')
            else:
                messages.success(request, '登录成功！')
            
            # Login the user
            login(request, target_user)
            
            # Redirect to next parameter or default
            next_url = request.GET.get('next', '/')
            return redirect(next_url)
    else:
        form = PhoneAuthenticationForm()
    
    return render(request, 'registration/login.html', {
        'form': form,
        'is_temp_user': is_temp_user,
        'next': request.GET.get('next', '/')
    })
