#!/usr/bin/env python
"""
Unit tests for TemporaryUserRegistrationForm.
Tests the specific bug fix for profile field saving, especially twin_type=0.
"""
import os
import django
from django.test import TestCase
from django.contrib.auth import get_user_model
from datetime import date, time
import uuid

# Setup Django
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'iching.settings')
os.environ.setdefault('DJANGO_ENV', 'development')

# Import models and forms
from accounts.models import UserProfile
from accounts.forms import TemporaryUserRegistrationForm
from accounts.utils import get_first_bazi_record, extract_user_data_from_bazi
from bazi.models import Person

User = get_user_model()


class TemporaryUserRegistrationFormTestCase(TestCase):
    """Test cases for TemporaryUserRegistrationForm"""
    
    def setUp(self):
        """Set up test data"""
        # Create unique identifiers for each test
        self.unique_id = str(uuid.uuid4())[:8]
        
        # Create a temporary user for testing
        self.temp_user = User.objects.create_user(
            phone=f'temp_test_{self.unique_id}',
            email=f'temp_{self.unique_id}@test.com',
            is_temporary_user=True
        )
        
        # Create profile for the temp user
        self.profile, created = UserProfile.objects.get_or_create(user=self.temp_user)
    
    def tearDown(self):
        """Clean up after each test"""
        # Clean up users created during tests
        User.objects.filter(phone__contains=self.unique_id).delete()


class TempUserRegistrationFormSaveTests(TemporaryUserRegistrationFormTestCase):
    """Test the form's save method with focus on the bug fix"""
    
    def test_twin_type_zero_saved_correctly(self):
        """Test that twin_type=0 (正常) is saved correctly - this was the main bug"""
        test_data = {
            'phone': f'1234567890_{self.unique_id}',
            'email': f'test_{self.unique_id}@example.com',
            'first_name': 'Test',
            'last_name': 'User',
            'birth_date': '1990-01-01',
            'birth_time': '12:00',
            'twin_type': '0',  # This was the problematic value
            'father_dob': '1960-01-01',
            'mother_dob': '1965-01-01'
        }
        
        form = TemporaryUserRegistrationForm(temp_user=self.temp_user, data=test_data)
        self.assertTrue(form.is_valid(), f"Form should be valid. Errors: {form.errors}")
        
        # Save the form
        converted_user = form.save(self.temp_user)
        converted_user.refresh_from_db()
        
        # Check that twin_type=0 was saved correctly
        self.assertEqual(converted_user.profile.twin_type, 0)
        self.assertEqual(converted_user.profile.birth_date, date(1990, 1, 1))
        self.assertEqual(converted_user.profile.birth_time, time(12, 0))
        self.assertEqual(converted_user.profile.father_dob, date(1960, 1, 1))
        self.assertEqual(converted_user.profile.mother_dob, date(1965, 1, 1))
    
    def test_twin_type_one_saved_correctly(self):
        """Test that twin_type=1 (双胞胎大) is saved correctly"""
        test_data = {
            'phone': f'1234567891_{self.unique_id}',
            'email': f'test1_{self.unique_id}@example.com',
            'first_name': 'Test',
            'last_name': 'User',
            'twin_type': '1',  # 双胞胎大
            'father_dob': '1960-01-01',  # Required for twin_type=1
        }
        
        form = TemporaryUserRegistrationForm(temp_user=self.temp_user, data=test_data)
        self.assertTrue(form.is_valid(), f"Form should be valid. Errors: {form.errors}")
        
        # Save the form
        converted_user = form.save(self.temp_user)
        converted_user.refresh_from_db()
        
        # Check that twin_type=1 was saved correctly
        self.assertEqual(converted_user.profile.twin_type, 1)
        self.assertEqual(converted_user.profile.father_dob, date(1960, 1, 1))
    
    def test_twin_type_two_saved_correctly(self):
        """Test that twin_type=2 (双胞胎小) is saved correctly"""
        test_data = {
            'phone': f'1234567892_{self.unique_id}',
            'email': f'test2_{self.unique_id}@example.com',
            'first_name': 'Test',
            'last_name': 'User',
            'twin_type': '2',  # 双胞胎小
            'mother_dob': '1965-01-01',  # Required for twin_type=2
        }
        
        form = TemporaryUserRegistrationForm(temp_user=self.temp_user, data=test_data)
        self.assertTrue(form.is_valid(), f"Form should be valid. Errors: {form.errors}")
        
        # Save the form
        converted_user = form.save(self.temp_user)
        converted_user.refresh_from_db()
        
        # Check that twin_type=2 was saved correctly
        self.assertEqual(converted_user.profile.twin_type, 2)
        self.assertEqual(converted_user.profile.mother_dob, date(1965, 1, 1))
    
    def test_all_profile_fields_saved_correctly(self):
        """Test that all profile fields are saved correctly"""
        test_data = {
            'phone': f'1234567893_{self.unique_id}',
            'email': f'test3_{self.unique_id}@example.com',
            'first_name': 'John',
            'last_name': 'Doe',
            'gender': 'M',
            'birth_date': '1985-12-25',
            'birth_time': '15:30',
            'twin_type': '0',
            'father_dob': '1955-06-15',
            'mother_dob': '1958-09-22'
        }
        
        form = TemporaryUserRegistrationForm(temp_user=self.temp_user, data=test_data)
        self.assertTrue(form.is_valid(), f"Form should be valid. Errors: {form.errors}")
        
        # Save the form
        converted_user = form.save(self.temp_user)
        converted_user.refresh_from_db()
        
        # Check user fields
        self.assertEqual(converted_user.first_name, 'John')
        self.assertEqual(converted_user.last_name, 'Doe')
        self.assertEqual(converted_user.gender, 'M')
        self.assertFalse(converted_user.is_temporary_user)
        
        # Check profile fields
        profile = converted_user.profile
        self.assertEqual(profile.birth_date, date(1985, 12, 25))
        self.assertEqual(profile.birth_time, time(15, 30))
        self.assertEqual(profile.twin_type, 0)
        self.assertEqual(profile.father_dob, date(1955, 6, 15))
        self.assertEqual(profile.mother_dob, date(1958, 9, 22))
    
    def test_partial_update_preserves_existing_data(self):
        """Test that partial updates preserve existing profile data"""
        # Pre-populate the profile with some data
        self.profile.birth_date = date(1990, 1, 1)
        self.profile.twin_type = 1
        self.profile.father_dob = date(1960, 1, 1)
        self.profile.save()
        
        # Test form data that explicitly includes twin_type and other fields
        test_data = {
            'phone': f'1234567894_{self.unique_id}',
            'email': f'test4_{self.unique_id}@example.com',
            'first_name': 'Test',
            'last_name': 'User',
            'birth_date': '1995-05-05',  # This should update
            'twin_type': '1',  # Keep existing value
            'father_dob': '1960-01-01',  # Keep existing value
        }
        
        form = TemporaryUserRegistrationForm(temp_user=self.temp_user, data=test_data)
        self.assertTrue(form.is_valid(), f"Form should be valid. Errors: {form.errors}")
        
        # Save the form
        converted_user = form.save(self.temp_user)
        converted_user.refresh_from_db()
        
        # Check that all fields were saved correctly
        self.assertEqual(converted_user.profile.birth_date, date(1995, 5, 5))  # Updated
        self.assertEqual(converted_user.profile.twin_type, 1)  # Preserved
        self.assertEqual(converted_user.profile.father_dob, date(1960, 1, 1))  # Preserved


class TempUserRegistrationFormPrefillingTests(TemporaryUserRegistrationFormTestCase):
    """Test form pre-filling from BaZi records"""
    
    def test_form_prefilled_from_bazi_record(self):
        """Test that form is pre-filled with data from BaZi record"""
        # Create a BaZi record with detailed information
        bazi_record = Person.objects.create(
            name='张三',
            gender='M',
            birth_date=date(1990, 1, 1),
            birth_time=time(12, 0),
            twin_type=1,
            father_dob=date(1960, 1, 1),
            mother_dob=date(1965, 1, 1),
            created_by=self.temp_user,
            created_by_temp_user=True,
            owner=True
        )
        
        # Create form without providing data (should pre-fill from BaZi)
        form = TemporaryUserRegistrationForm(temp_user=self.temp_user)
        
        # Check that fields are pre-filled correctly
        self.assertEqual(form.fields['first_name'].initial, '三')
        self.assertEqual(form.fields['last_name'].initial, '张')
        self.assertEqual(form.fields['gender'].initial, 'M')
        self.assertEqual(form.fields['birth_date'].initial, date(1990, 1, 1))
        self.assertEqual(form.fields['birth_time'].initial, time(12, 0))
        self.assertEqual(form.fields['twin_type'].initial, 1)
        self.assertEqual(form.fields['father_dob'].initial, date(1960, 1, 1))
        self.assertEqual(form.fields['mother_dob'].initial, date(1965, 1, 1))
    
    def test_user_scenario_liuyao_then_bazi_then_register(self):
        """Test the user's reported scenario: LiuYao first, then BaZi, then register"""
        # Create a BaZi record (simulating user creating BaZi after LiuYao)
        bazi_record = Person.objects.create(
            name='李四',
            gender='F',
            birth_date=date(1992, 5, 15),
            birth_time=time(8, 30),
            twin_type=0,  # 正常 - this was the problematic value
            father_dob=date(1965, 3, 10),
            mother_dob=date(1970, 8, 20),
            created_by=self.temp_user,
            created_by_temp_user=True,
            owner=True  # This should be the first BaZi record, so it's the owner
        )
        
        # Test form pre-filling
        form = TemporaryUserRegistrationForm(temp_user=self.temp_user)
        
        # Verify all data is pre-filled
        self.assertEqual(form.fields['first_name'].initial, '四')
        self.assertEqual(form.fields['last_name'].initial, '李')
        self.assertEqual(form.fields['gender'].initial, 'F')
        self.assertEqual(form.fields['birth_date'].initial, date(1992, 5, 15))
        self.assertEqual(form.fields['birth_time'].initial, time(8, 30))
        self.assertEqual(form.fields['twin_type'].initial, 0)  # This was the bug
        self.assertEqual(form.fields['father_dob'].initial, date(1965, 3, 10))
        self.assertEqual(form.fields['mother_dob'].initial, date(1970, 8, 20))
        
        # Test form submission with the pre-filled data
        test_data = {
            'phone': f'1234567895_{self.unique_id}',
            'email': f'test5_{self.unique_id}@example.com',
            'first_name': '李',
            'last_name': '四',
            'gender': 'F',
            'birth_date': '1992-05-15',
            'birth_time': '08:30',
            'twin_type': '0',  # This was the main issue
            'father_dob': '1965-03-10',
            'mother_dob': '1970-08-20'
        }
        
        form_with_data = TemporaryUserRegistrationForm(temp_user=self.temp_user, data=test_data)
        self.assertTrue(form_with_data.is_valid(), f"Form should be valid. Errors: {form_with_data.errors}")
        
        # Save the form
        converted_user = form_with_data.save(self.temp_user)
        converted_user.refresh_from_db()
        
        # Verify ALL fields are saved correctly, especially twin_type=0
        self.assertEqual(converted_user.first_name, '李')
        self.assertEqual(converted_user.last_name, '四')
        self.assertEqual(converted_user.gender, 'F')
        self.assertEqual(converted_user.profile.birth_date, date(1992, 5, 15))
        self.assertEqual(converted_user.profile.birth_time, time(8, 30))
        self.assertEqual(converted_user.profile.twin_type, 0)  # This was the bug fix
        self.assertEqual(converted_user.profile.father_dob, date(1965, 3, 10))
        self.assertEqual(converted_user.profile.mother_dob, date(1970, 8, 20))


class TempUserRegistrationFormValidationTests(TemporaryUserRegistrationFormTestCase):
    """Test form validation"""
    
    def test_twin_type_validation_with_required_fields(self):
        """Test validation for twin_type requiring specific fields"""
        # Test twin_type=1 requires father_dob
        test_data = {
            'phone': f'1234567896_{self.unique_id}',
            'email': f'test6_{self.unique_id}@example.com',
            'twin_type': '1',  # 双胞胎大
            # Missing father_dob
        }
        
        form = TemporaryUserRegistrationForm(temp_user=self.temp_user, data=test_data)
        self.assertFalse(form.is_valid())
        self.assertIn('father_dob', form.errors)
        
        # Test twin_type=2 requires mother_dob
        test_data['twin_type'] = '2'  # 双胞胎小
        # Missing mother_dob
        
        form = TemporaryUserRegistrationForm(temp_user=self.temp_user, data=test_data)
        self.assertFalse(form.is_valid())
        self.assertIn('mother_dob', form.errors)
    
    def test_password_validation(self):
        """Test password validation"""
        test_data = {
            'phone': f'1234567897_{self.unique_id}',
            'email': f'test7_{self.unique_id}@example.com',
            'password': 'test123',
            'password2': 'different123',  # Passwords don't match
        }
        
        form = TemporaryUserRegistrationForm(temp_user=self.temp_user, data=test_data)
        self.assertFalse(form.is_valid())
        self.assertIn('password2', form.errors)
    
    def test_duplicate_phone_email_validation(self):
        """Test validation for duplicate phone and email"""
        # Create another user with specific phone/email
        other_user = User.objects.create_user(
            phone=f'existing_{self.unique_id}',
            email=f'existing_{self.unique_id}@example.com'
        )
        
        test_data = {
            'phone': f'existing_{self.unique_id}',  # Duplicate phone
            'email': f'test8_{self.unique_id}@example.com',
        }
        
        form = TemporaryUserRegistrationForm(temp_user=self.temp_user, data=test_data)
        self.assertFalse(form.is_valid())
        self.assertIn('phone', form.errors)
        
        # Test duplicate email
        test_data['phone'] = f'unique_{self.unique_id}'
        test_data['email'] = f'existing_{self.unique_id}@example.com'  # Duplicate email
        
        form = TemporaryUserRegistrationForm(temp_user=self.temp_user, data=test_data)
        self.assertFalse(form.is_valid())
        self.assertIn('email', form.errors)


if __name__ == '__main__':
    django.setup()
    import unittest
    unittest.main() 