"""
Test BaZi → LiuYao temp user continuity scenario
This test verifies the exact scenario described by the user:
1. Public user creates BaZi record first - temp user created and has auth session
2. User proceeds to create LiuYao record - should reuse same temp user (not create new one)
3. User can see both BaZi and LiuYao records since they belong to the same temp user
"""

from django.test import TestCase, Client
from django.contrib.auth import get_user_model
from django.urls import reverse
from bazi.models import Person
from liuyao.models import liuyao
from django.contrib.sessions.models import Session
import json

User = get_user_model()

class BaziLiuyaoTempUserContinuityTest(TestCase):
    """Test the exact BaZi → LiuYao temp user continuity scenario"""

    def setUp(self):
        self.client = Client()

    def test_bazi_then_liuyao_same_temp_user_full_scenario(self):
        """
        Test the complete scenario:
        1. Create BaZi record (creates temp user 247 with session)
        2. Create LiuYao record (should reuse temp user 247, not create 248)
        3. Verify both records belong to same user
        4. Verify user can access both records
        """
        
        print("🎯 Testing BaZi → LiuYao temp user continuity scenario")
        
        # Step 1: Simulate BaZi record creation flow
        print("\n📊 Step 1: Creating BaZi record (should create temp user)")
        
        # Create temp user via API (simulating BaZi middleware creating temp user)
        bazi_response = self.client.post(
            reverse('api:temp_user_create'),
            json.dumps({'name': 'BaZi User'}),
            content_type='application/json'
        )
        self.assertEqual(bazi_response.status_code, 201)
        bazi_temp_user_data = bazi_response.json()
        bazi_user_id = bazi_temp_user_data['user_id']
        
        print(f"   ✓ Temp user {bazi_user_id} created for BaZi flow")
        
        # Convert JWT to session (establishing session auth like BaZi middleware does)
        session_response = self.client.post(
            reverse('api:jwt_to_session'),
            json.dumps({'access_token': bazi_temp_user_data['access']}),
            content_type='application/json'
        )
        self.assertEqual(session_response.status_code, 200)
        print(f"   ✓ Session auth established for user {bazi_user_id}")
        
        # Create a BaZi record via API (simulating what happens after temp user creation)
        bazi_record_data = {
            'name': 'Test Person',
            'gender': 'M',
            'birth_date': '1990-05-15',
            'birth_time': '10:30:00',
            'twin_type': 0,
            'notes': 'Test BaZi record'
        }
        
        bazi_create_response = self.client.post(
            reverse('api:bazi-list'),
            json.dumps(bazi_record_data),
            content_type='application/json'
        )
        self.assertEqual(bazi_create_response.status_code, 201)
        bazi_record = bazi_create_response.json()
        print(f"   ✓ BaZi record {bazi_record['id']} created for user {bazi_user_id}")
        
        # Verify BaZi record belongs to correct user
        bazi_person = Person.objects.get(id=bazi_record['id'])
        self.assertEqual(bazi_person.created_by.id, bazi_user_id)
        print(f"   ✓ Verified BaZi record belongs to user {bazi_user_id}")
        
        # Step 2: Record current state before LiuYao creation
        print("\n📈 Step 2: Checking state before LiuYao creation")
        
        temp_users_before = User.objects.filter(is_temporary_user=True).count()
        print(f"   📊 Temp users before LiuYao: {temp_users_before}")
        
        # Step 3: Simulate LiuYao record creation (should reuse existing temp user)
        print("\n🧿 Step 3: Creating LiuYao record (should reuse existing temp user)")
        
        # The key test: LiuYao JavaScript should detect existing session and NOT create new user
        # This is simulated by checking that the session user is still the same
        
        # Verify session is still active for the same user
        response = self.client.get(reverse('main:index'))
        self.assertEqual(response.status_code, 200)
        print("   ✓ Session still active")
        
        # Create LiuYao record via API (simulating LiuYao flow)
        liuyao_data = {
            'question': 'Test question',
            'qdate': '2024-01-15T14:30:00Z',
            'y1': '1', 'y2': '0', 'y3': '1', 'y4': '0', 'y5': '1', 'y6': '0'
        }
        
        liuyao_response = self.client.post(
            reverse('api:liuyao-list'),
            json.dumps(liuyao_data),
            content_type='application/json'
        )
        self.assertEqual(liuyao_response.status_code, 201)
        liuyao_record = liuyao_response.json()
        
        # Get the record ID from the response (may be different field name)
        liuyao_record_id = liuyao_record.get('id') or liuyao_record.get('pk') or liuyao_record.get('uuid')
        print(f"   ✓ LiuYao record created successfully")
        
        # Step 4: Verify no new temp user was created
        print("\n🔍 Step 4: Verifying temp user continuity")
        
        temp_users_after = User.objects.filter(is_temporary_user=True).count()
        print(f"   📊 Temp users after LiuYao: {temp_users_after}")
        
        # Critical assertion: should be same number of temp users
        self.assertEqual(temp_users_before, temp_users_after, 
                        "LiuYao creation should NOT create new temp user")
        print("   ✅ No new temp user created - continuity maintained!")
        
        # Step 5: Verify both records belong to the same user
        print("\n👤 Step 5: Verifying record ownership")
        
        # Find the LiuYao record using the question since ID not in response
        liuyao_obj = liuyao.objects.get(question='Test question')
        liuyao_record_id = liuyao_obj.id
        print(f"   ✓ Found LiuYao record with ID: {liuyao_record_id}")
        
        # Both records should belong to the same temp user
        self.assertEqual(bazi_person.created_by.id, liuyao_obj.user.id,
                        "BaZi and LiuYao records should belong to same temp user")
        self.assertEqual(bazi_person.created_by.id, bazi_user_id)
        self.assertEqual(liuyao_obj.user.id, bazi_user_id)
        
        print(f"   ✓ BaZi record belongs to user {bazi_person.created_by.id}")
        print(f"   ✓ LiuYao record belongs to user {liuyao_obj.user.id}")
        print(f"   ✅ Both records belong to same temp user {bazi_user_id}")
        
        # Step 6: Verify user can access both records
        print("\n📋 Step 6: Verifying data accessibility")
        
        # Get BaZi records for the user
        bazi_list_response = self.client.get(reverse('api:bazi-list'))
        self.assertEqual(bazi_list_response.status_code, 200)
        bazi_list = bazi_list_response.json()
        
        # Get LiuYao records for the user  
        liuyao_list_response = self.client.get(reverse('api:liuyao-list'))
        self.assertEqual(liuyao_list_response.status_code, 200)
        liuyao_list = liuyao_list_response.json()
        
        # Both lists should contain the respective records
        bazi_ids = [record['id'] for record in bazi_list['results']]
        liuyao_questions = [record.get('question') for record in liuyao_list['results']]
        
        self.assertIn(bazi_record['id'], bazi_ids, "User should see their BaZi record")
        self.assertIn('Test question', liuyao_questions, "User should see their LiuYao record")
        
        print(f"   ✓ User can access BaZi record: {bazi_record['id']}")
        print(f"   ✓ User can access LiuYao record: {liuyao_record_id}")
        print("   ✅ All data accessible to the same temp user!")
        
        # Step 7: Final verification
        print("\n🎉 Step 7: Final verification")
        
        temp_user = User.objects.get(id=bazi_user_id)
        self.assertTrue(temp_user.is_temporary_user)
        
        # Count records for this user
        user_bazi_count = Person.objects.filter(created_by=temp_user).count()
        user_liuyao_count = liuyao.objects.filter(user=temp_user).count()
        
        self.assertEqual(user_bazi_count, 1, "Should have 1 BaZi record")
        self.assertEqual(user_liuyao_count, 1, "Should have 1 LiuYao record")
        
        print(f"   📊 Temp user {bazi_user_id} has:")
        print(f"       - {user_bazi_count} BaZi record(s)")
        print(f"       - {user_liuyao_count} LiuYao record(s)")
        print("   ✅ Perfect data continuity achieved!")
        
        print("\n🎯 ✅ BaZi → LiuYao temp user continuity test PASSED!")
        
    def test_multiple_bazi_then_liuyao_same_user(self):
        """Test creating multiple BaZi records then LiuYao - all should belong to same temp user"""
        
        print("\n🔄 Testing multiple BaZi → LiuYao with same temp user")
        
        # Create temp user and session
        response = self.client.post(
            reverse('api:temp_user_create'),
            json.dumps({'name': 'Multi Record User'}),
            content_type='application/json'
        )
        temp_user_data = response.json()
        temp_user_id = temp_user_data['user_id']
        
        # Establish session
        self.client.post(
            reverse('api:jwt_to_session'),
            json.dumps({'access_token': temp_user_data['access']}),
            content_type='application/json'
        )
        
        print(f"   ✓ Created temp user {temp_user_id}")
        
        # Create multiple BaZi records
        bazi_records = []
        for i in range(3):
            bazi_data = {
                'name': f'Person {i+1}',
                'gender': 'M',
                'birth_date': f'{1990 + i}-05-15',
                'birth_time': '10:30:00',
                'twin_type': 0,
                'notes': f'Test BaZi record {i+1}'
            }
            
            bazi_response = self.client.post(
                reverse('api:bazi-list'),
                json.dumps(bazi_data),
                content_type='application/json'
            )
            self.assertEqual(bazi_response.status_code, 201)
            bazi_records.append(bazi_response.json())
        
        print(f"   ✓ Created {len(bazi_records)} BaZi records")
        
        # Create multiple LiuYao records
        liuyao_records = []
        for i in range(2):
            liuyao_data = {
                'question': f'Question {i+1}',
                'qdate': f'2024-01-{15 + i}T14:30:00Z',
                'y1': str(i % 2), 'y2': str((i+1) % 2), 'y3': str(i % 2), 
                'y4': str((i+1) % 2), 'y5': str(i % 2), 'y6': str((i+1) % 2)
            }
            
            liuyao_response = self.client.post(
                reverse('api:liuyao-list'),
                json.dumps(liuyao_data),
                content_type='application/json'
            )
            self.assertEqual(liuyao_response.status_code, 201)
            liuyao_records.append(liuyao_response.json())
        
        print(f"   ✓ Created {len(liuyao_records)} LiuYao records")
        
        # Verify all records belong to the same temp user
        temp_user = User.objects.get(id=temp_user_id)
        
        bazi_count = Person.objects.filter(created_by=temp_user).count()
        liuyao_count = liuyao.objects.filter(user=temp_user).count()
        
        self.assertEqual(bazi_count, 3, "Should have 3 BaZi records")
        self.assertEqual(liuyao_count, 2, "Should have 2 LiuYao records")
        
        # Verify only one temp user exists
        total_temp_users = User.objects.filter(is_temporary_user=True).count()
        self.assertEqual(total_temp_users, 1, "Should only have 1 temp user")
        
        print(f"   ✅ All records belong to same temp user {temp_user_id}")
        print("   ✅ Multiple records continuity test PASSED!")
        
    def test_liuyao_first_then_bazi_same_user(self):
        """Test reverse scenario: LiuYao first, then BaZi - should use same temp user"""
        
        print("\n🔄 Testing LiuYao → BaZi temp user continuity")
        
        # Create temp user via LiuYao flow
        response = self.client.post(
            reverse('api:temp_user_create'),
            json.dumps({'name': 'LiuYao First User'}),
            content_type='application/json'
        )
        temp_user_data = response.json()
        temp_user_id = temp_user_data['user_id']
        
        # Establish session
        self.client.post(
            reverse('api:jwt_to_session'),
            json.dumps({'access_token': temp_user_data['access']}),
            content_type='application/json'
        )
        
        print(f"   ✓ Created temp user {temp_user_id} via LiuYao flow")
        
        # Create LiuYao record first
        liuyao_data = {
            'question': 'First question',
            'qdate': '2024-01-15T14:30:00Z',
            'y1': '1', 'y2': '0', 'y3': '1', 'y4': '0', 'y5': '1', 'y6': '0'
        }
        
        liuyao_response = self.client.post(
            reverse('api:liuyao-list'),
            json.dumps(liuyao_data),
            content_type='application/json'
        )
        self.assertEqual(liuyao_response.status_code, 201)
        liuyao_record = liuyao_response.json()
        print(f"   ✓ Created LiuYao record {liuyao_record.get('question', 'Unknown')}")
        
        # Now create BaZi record (should reuse same temp user)
        bazi_data = {
            'name': 'BaZi After LiuYao',
            'gender': 'F',
            'birth_date': '1995-08-20',
            'birth_time': '14:15:00',
            'twin_type': 0,
            'notes': 'BaZi after LiuYao test'
        }
        
        bazi_response = self.client.post(
            reverse('api:bazi-list'),
            json.dumps(bazi_data),
            content_type='application/json'
        )
        self.assertEqual(bazi_response.status_code, 201)
        bazi_record = bazi_response.json()
        print(f"   ✓ Created BaZi record {bazi_record['id']}")
        
        # Verify both records belong to same temp user
        temp_user = User.objects.get(id=temp_user_id)
        bazi_person = Person.objects.get(id=bazi_record['id'])
        liuyao_obj = liuyao.objects.get(question='First question')
        
        self.assertEqual(bazi_person.created_by.id, temp_user_id)
        self.assertEqual(liuyao_obj.user.id, temp_user_id)
        
        # Verify only one temp user exists
        total_temp_users = User.objects.filter(is_temporary_user=True).count()
        self.assertEqual(total_temp_users, 1, "Should only have 1 temp user")
        
        print(f"   ✅ Both records belong to temp user {temp_user_id}")
        print("   ✅ LiuYao → BaZi continuity test PASSED!")

if __name__ == '__main__':
    import django
    import os
    
    os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'iching.settings')
    django.setup()
    
    from django.test.utils import get_runner
    from django.conf import settings
    
    TestRunner = get_runner(settings)
    test_runner = TestRunner()
    failures = test_runner.run_tests(["tests.test_bazi_liuyao_temp_user_continuity"]) 