from django.shortcuts import render, redirect, get_object_or_404
from django.contrib.auth.decorators import login_required
from django.contrib import messages
from django.contrib.auth import login
from django.views.generic import ListView
from django.contrib.auth.mixins import LoginRequiredMixin
from django.http import HttpResponseRedirect
from django.urls import reverse
from .forms import PersonForm
from .models import Person
from iching.utils.bz import getDateTimeGodEarthStem, gGodstem, gEarthstem, findGodstem5E
from django.conf import settings
import json
from iching.utils.bzshagod import gShagodNames
from accounts.utils import create_temporary_user

def home(request):
    return render(request, 'bazi/home.html')

def calculate_chart(request):
    if request.method == 'POST':
        form = PersonForm(request.POST)
        if form.is_valid():
            person = form.save(commit=False)
            
            # Handle authentication - create temporary user if needed
            if not request.user.is_authenticated:
                # Extract user data from form for temporary user creation
                from accounts.utils import extract_first_last_name
                
                # Get name and split into first/last name
                full_name = person.name or ''
                first_name, last_name = extract_first_last_name(full_name)
                
                # Prepare user data for temporary user creation (only BaZi form fields)
                # Convert date/time objects to strings for processing in create_temporary_user
                user_data = {
                    'name': person.name,
                    'first_name': first_name,
                    'last_name': last_name,
                    'gender': person.gender,
                    'birth_date': person.birth_date.strftime('%Y-%m-%d') if person.birth_date else None,
                    'birth_time': person.birth_time.strftime('%H:%M') if person.birth_time else None,
                    # Note: twin_type, father_dob, mother_dob are not in BaZi form
                }
                
                # Create temporary user with extracted data and log them in
                temp_user = create_temporary_user(user_data)
                login(request, temp_user)
                
                # Check if signal already created an owner record with BaZi calculation
                try:
                    existing_owner = Person.objects.get(created_by=temp_user, owner=True)
                    if existing_owner.bazi_result:
                        # Signal already created the record with BaZi calculation, use it
                        person = existing_owner
                        bazi_result = person.bazi_result
                    else:
                        # Signal created owner record but no BaZi calculation, calculate it
                        bazi_result = existing_owner.calculate_bazi()
                        existing_owner.save()
                        person = existing_owner
                except Person.DoesNotExist:
                    # No owner record exists, check if this should be the first owner record
                    existing_records = Person.objects.filter(created_by=temp_user).count()
                    is_first_record = existing_records == 0
                    
                    person.created_by = temp_user
                    person.created_by_temp_user = True
                    person.owner = is_first_record  # First record becomes owner, others are calculations
                    bazi_result = person.calculate_bazi()
                    person.save()
            else:
                # For authenticated users, check if this should be their first owner record
                existing_records = Person.objects.filter(created_by=request.user).count()
                is_first_record = existing_records == 0
                
                person.created_by = request.user
                person.owner = is_first_record  # First record becomes owner, others are calculations
                # Set flag if user is temporary
                if hasattr(request.user, 'is_temporary_user') and request.user.is_temporary_user:
                    person.created_by_temp_user = True
                # Calculate BaZi
                bazi_result = person.calculate_bazi()
                person.save()
            messages.success(request, 'Chart calculated and saved successfully.')
            return redirect('bazi:person_detail', pk=person.pk)
    else:
        form = PersonForm()
    
    return render(request, 'bazi/calculate.html', {'form': form})

@login_required
def person_detail(request, pk):
    person = get_object_or_404(Person, pk=pk, created_by=request.user)
    # Get configurable message limit
    from ai.models import ConversationConfig
    max_messages = ConversationConfig.get_max_messages()
    # Pass god names to the template as JSON
    return render(request, 'bazi/person_detail.html', {
        'person': person,
        'max_messages': max_messages,
    })

class PersonListView(LoginRequiredMixin, ListView):
    model = Person
    template_name = 'bazi/person_list.html'
    context_object_name = 'persons'
    
    def get_paginate_by(self, queryset):
        """
        Get the number of items to paginate by, or use settings default
        """
        # Check if user has set a preference in their session
        session_value = self.request.session.get('bazi_items_per_page')
        if session_value:
            return session_value
        
        # Check URL parameter (allow temporary override)
        url_value = self.request.GET.get('per_page')
        if url_value and url_value.isdigit() and 5 <= int(url_value) <= 100:
            return int(url_value)
            
        # Fall back to settings with app-specific default
        return settings.PAGINATE_BY.get('bazi', settings.PAGINATE_BY['default'])
    
    def get_queryset(self):
        # Get all records except the user's own record
        return Person.objects.filter(
            created_by=self.request.user,
            owner=False  # Exclude the user's own record
        ).order_by('-created_at')
    
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        
        # Get the user's own record
        try:
            user_record = Person.objects.get(
                created_by=self.request.user,
                owner=True
            )
            # Add BaZi display data for the user's own record
            if user_record.bazi_result:
                display_data = {
                    'day': {
                        'god': gGodstem[user_record.bazi_result['day']['god']],
                        'earth': gEarthstem[user_record.bazi_result['day']['earth']],
                        'element': findGodstem5E(user_record.bazi_result['day']['god'])['e']
                    },
                    'month': {
                        'god': gGodstem[user_record.bazi_result['month']['god']],
                        'earth': gEarthstem[user_record.bazi_result['month']['earth']]
                    },
                    'year': {
                        'god': gGodstem[user_record.bazi_result['year']['god']],
                        'earth': gEarthstem[user_record.bazi_result['year']['earth']]
                    }
                }
                
                if 'hour' in user_record.bazi_result and user_record.bazi_result['hour'].get('god') is not None and user_record.bazi_result['hour'].get('earth') is not None:
                    display_data['hour'] = {
                        'god': gGodstem[user_record.bazi_result['hour']['god']],
                        'earth': gEarthstem[user_record.bazi_result['hour']['earth']]
                    }
                
                user_record.bazi_display = display_data
            context['user_record'] = user_record
        except Person.DoesNotExist:
            context['user_record'] = None
        
        # Add BaZi display data for each person in the list
        for person in context['persons']:
            if person.bazi_result:
                display_data = {
                    'day': {
                        'god': gGodstem[person.bazi_result['day']['god']],
                        'earth': gEarthstem[person.bazi_result['day']['earth']],
                        'element': findGodstem5E(person.bazi_result['day']['god'])['e']
                    },
                    'month': {
                        'god': gGodstem[person.bazi_result['month']['god']],
                        'earth': gEarthstem[person.bazi_result['month']['earth']]
                    },
                    'year': {
                        'god': gGodstem[person.bazi_result['year']['god']],
                        'earth': gEarthstem[person.bazi_result['year']['earth']]
                    }
                }
                
                if 'hour' in person.bazi_result and person.bazi_result['hour'].get('god') is not None and person.bazi_result['hour'].get('earth') is not None:
                    display_data['hour'] = {
                        'god': gGodstem[person.bazi_result['hour']['god']],
                        'earth': gEarthstem[person.bazi_result['hour']['earth']]
                    }
                
                person.bazi_display = display_data
        
        # Add pagination context
        paginator = context['paginator']
        page_obj = context['page_obj']
        
        # Calculate page range (show 5 pages around current page)
        page_range = []
        current_page = page_obj.number
        total_pages = paginator.num_pages
        
        if total_pages <= 5:
            page_range = range(1, total_pages + 1)
        else:
            start_page = max(current_page - 2, 1)
            end_page = min(start_page + 4, total_pages)
            
            if end_page == total_pages:
                start_page = max(end_page - 4, 1)
                
            page_range = range(start_page, end_page + 1)
        
        context['page_range'] = page_range
        
        return context

@login_required
def delete_person(request, pk):
    person = get_object_or_404(Person, pk=pk, created_by=request.user)
    if request.method == 'POST':
        person.delete()
        messages.success(request, 'Chart deleted successfully.')
        return HttpResponseRedirect(reverse('bazi:person_list'))
    return redirect('bazi:person_list')

@login_required
def person_relations(request):
    """View for displaying person relationships analysis"""
    # Get the current user's BaZi record
    current_user_bazi = None
    if request.user.is_authenticated:
        try:
            owner_person = Person.objects.filter(
                created_by=request.user, 
                owner=True
            ).first()
            if owner_person:
                # Calculate BaZi result for the owner
                bazi_data = owner_person.calculate_bazi()
                current_user_bazi = {
                    'id': owner_person.id,
                    'name': owner_person.name,
                    'owner': True,
                    'bazi_result': bazi_data
                }
        except Exception as e:
            # Log the error but don't fail the page load
            print(f"Error loading current user BaZi: {e}")
    
    context = {
        'current_user_bazi': json.dumps(current_user_bazi) if current_user_bazi else None
    }
    return render(request, 'bazi/person_relations.html', context)
