import re
import secrets
import string
from django.contrib.auth import get_user_model
from django.utils import timezone
from django.db import transaction

def extract_first_last_name(full_name):
    """
    Extract first and last name from a full name string.
    
    For Chinese names: first character is last name, rest is first name
    For non-Chinese names: split by space, last word is last name, rest is first name
    
    Args:
        full_name (str): The full name to split
        
    Returns:
        tuple: (first_name, last_name)
    """
    if not full_name or not full_name.strip():
        return '', ''
    
    full_name = full_name.strip()
    
    if is_chinese(full_name):
        # Chinese name: first character is last name, rest is first name
        if len(full_name) == 1:
            return '', full_name
        else:
            last_name = full_name[0]
            first_name = full_name[1:]
            return first_name, last_name
    else:
        # Non-Chinese name: split by space
        name_parts = full_name.split()
        if len(name_parts) == 1:
            # Single name, treat as first name
            return name_parts[0], ''
        else:
            # Multiple parts: last is last name, rest is first name
            first_name = ' '.join(name_parts[:-1])
            last_name = name_parts[-1]
            return first_name, last_name


def is_chinese(text):
    """Check if the text contains Chinese characters."""
    return bool(re.search(r'[\u4e00-\u9fff]', text))


class NameFormatter:
    @staticmethod
    def format_name(first_name, last_name):
        """
        Format the name based on whether it contains Chinese characters.
        
        Args:
            first_name (str): The first name
            last_name (str): The last name
            
        Returns:
            str: Formatted name
        """
        # Remove any whitespace
        first_name = first_name.strip() if first_name else ''
        last_name = last_name.strip() if last_name else ''
        
        # Check if either name contains Chinese characters
        is_chinese_name = is_chinese(first_name) or is_chinese(last_name)
        
        if is_chinese_name:
            # For Chinese names, combine as last_name + first_name
            return f"{last_name}{first_name}"
        else:
            # For non-Chinese names, combine as first_name + space + last_name
            return f"{first_name} {last_name}".strip()


def create_temporary_user(user_data=None):
    """
    Create a temporary user with auto-generated credentials and optional user data.
    
    Args:
        user_data (dict, optional): User data from form (name, gender, birth_date, etc.)
    
    Returns:
        User: The created temporary user
    """
    User = get_user_model()
    
    timestamp = int(timezone.now().timestamp())
    random_suffix = ''.join(secrets.choice(string.ascii_lowercase + string.digits) for _ in range(8))
    
    temp_phone = f"temp_{timestamp}_{random_suffix}"
    temp_email = f"temp_{timestamp}_{random_suffix}@temp.local"
    temp_password = ''.join(secrets.choice(string.ascii_letters + string.digits) for _ in range(12))
    
    # Extract name information if provided
    first_name = ''
    last_name = ''
    gender = 'N'
    
    if user_data:
        # Extract first and last name from full name
        full_name = user_data.get('name', '')
        if full_name:
            first_name, last_name = extract_first_last_name(full_name)
        
        # Get gender
        gender = user_data.get('gender', 'N')
    
    user = User.objects.create_user(
        phone=temp_phone,
        email=temp_email,
        password=temp_password,
        first_name=first_name,
        last_name=last_name,
        gender=gender,
        is_temporary_user=True
    )
    
    # Create and populate user profile if user_data is provided
    if user_data:
        from accounts.models import UserProfile
        from datetime import datetime
        
        profile, created = UserProfile.objects.get_or_create(user=user)
        
        # Parse and set birth date
        birth_date_str = user_data.get('birth_date')
        if birth_date_str:
            try:
                # Handle various date formats
                birth_date_str = birth_date_str.replace('年', '-').replace('月', '-').replace('日', '')
                try:
                    profile.birth_date = datetime.strptime(birth_date_str, '%Y-%m-%d').date()
                except ValueError:
                    try:
                        profile.birth_date = datetime.strptime(birth_date_str, '%Y%m%d').date()
                    except ValueError:
                        pass  # Skip if date format is invalid
            except (ValueError, AttributeError):
                pass
        
        # Parse and set birth time
        birth_time_str = user_data.get('birth_time')
        if birth_time_str:
            try:
                profile.birth_time = datetime.strptime(birth_time_str, '%H:%M').time()
            except (ValueError, AttributeError):
                pass
        
        # Set twin type
        twin_type = user_data.get('twin_type')
        if twin_type:
            try:
                profile.twin_type = int(twin_type)
            except (ValueError, TypeError):
                pass
        
        # Parse and set father DOB
        father_dob_str = user_data.get('father_dob')
        if father_dob_str:
            try:
                father_dob_str = father_dob_str.replace('年', '-').replace('月', '-').replace('日', '')
                try:
                    profile.father_dob = datetime.strptime(father_dob_str, '%Y-%m-%d').date()
                except ValueError:
                    try:
                        profile.father_dob = datetime.strptime(father_dob_str, '%Y%m%d').date()
                    except ValueError:
                        pass
            except (ValueError, AttributeError):
                pass
        
        # Parse and set mother DOB
        mother_dob_str = user_data.get('mother_dob')
        if mother_dob_str:
            try:
                mother_dob_str = mother_dob_str.replace('年', '-').replace('月', '-').replace('日', '')
                try:
                    profile.mother_dob = datetime.strptime(mother_dob_str, '%Y-%m-%d').date()
                except ValueError:
                    try:
                        profile.mother_dob = datetime.strptime(mother_dob_str, '%Y%m%d').date()
                    except ValueError:
                        pass
            except (ValueError, AttributeError):
                pass
        
        profile.save()
        
        # Force refresh the user's profile relation to get the updated data
        user.refresh_from_db()
        profile.refresh_from_db()
    
    return user


def get_first_bazi_record(user):
    """
    Get the first BaZi record for a user.
    
    Args:
        user: User instance
        
    Returns:
        Person: First BaZi record or None
    """
    from bazi.models import Person
    try:
        return Person.objects.filter(created_by=user).order_by('created_at').first()
    except Person.DoesNotExist:
        return None


@transaction.atomic
def transfer_user_data(temp_user, target_user):
    """
    Transfer data from temporary user to target user.
    
    Args:
        temp_user: Temporary user instance
        target_user: Target user instance
        
    Returns:
        dict: Summary of transferred data
    """
    User = get_user_model()
    
    if not temp_user.is_temporary_user:
        raise ValueError("Source user is not a temporary user")
    
    # Import models to avoid circular imports
    from bazi.models import Person
    from liuyao.models import liuyao
    
    # Track transfer summary
    summary = {
        'bazi_records': 0,
        'liuyao_records': 0,
        'owner_flag_cleared': False
    }
    
    # Transfer BaZi records
    temp_bazi_records = Person.objects.filter(created_by=temp_user)
    target_has_owner = Person.objects.filter(created_by=target_user, owner=True).exists()
    
    for record in temp_bazi_records:
        # Clear owner flag if target already has owner record
        if target_has_owner and record.owner:
            record.owner = False
            summary['owner_flag_cleared'] = True
        
        record.created_by = target_user
        record.save()
        summary['bazi_records'] += 1
    
    # Transfer LiuYao records
    liuyao_records = liuyao.objects.filter(user=temp_user)
    liuyao_count = liuyao_records.update(user=target_user)
    summary['liuyao_records'] = liuyao_count
    
    return summary


def cleanup_temp_user(temp_user):
    """
    Clean up temporary user after data transfer.
    
    Args:
        temp_user: Temporary user instance
        
    Returns:
        bool: True if cleanup was successful
    """
    User = get_user_model()
    
    if not temp_user.is_temporary_user:
        raise ValueError("User is not a temporary user")
    
    # Import models to avoid circular imports
    from bazi.models import Person
    from liuyao.models import liuyao
    
    # Ensure all records have been transferred
    if (Person.objects.filter(created_by=temp_user).count() == 0 and 
        liuyao.objects.filter(user=temp_user).count() == 0):
        temp_user.delete()
        return True
    else:
        raise ValueError("Cannot cleanup user: records still exist")


def extract_user_data_from_bazi(bazi_person):
    """
    Extract user registration data from a BaZi person record.
    
    Args:
        bazi_person: Person instance
        
    Returns:
        dict: Extracted user data for form pre-filling
    """
    if not bazi_person:
        return {}
    
    # Split name into first and last name using helper function
    name = bazi_person.name or ''
    first_name, last_name = extract_first_last_name(name)
    
    return {
        'first_name': first_name,
        'last_name': last_name,
        'gender': bazi_person.gender,
        'birth_date': bazi_person.birth_date,
        'birth_time': bazi_person.birth_time,
        'twin_type': bazi_person.twin_type,
        'father_dob': bazi_person.father_dob,
        'mother_dob': bazi_person.mother_dob,
    } 