#!/usr/bin/env python
"""
old_rogdb から rogdb への全イベントデータ移行スクリプト（GPS情報含む）
FC岐阜の成功事例をベースに全てのイベントのteam/member/entry + GPS情報を移行
"""

import os
import sys
import django

if __name__ == '__main__':
    os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'config.settings')
    django.setup()
    
    from django.db import transaction, connection
    from rog.models import NewEvent2, Team, Entry, Member, NewCategory, CustomUser
    import psycopg2
    
    print("📋 全イベントデータ移行スクリプト（GPS情報含む）を開始します")
    
    # 各データベース接続設定
    OLD_DB_CONFIG = {
        'host': 'postgres-db',
        'port': 5432,
        'database': 'old_rogdb',
        'user': 'postgres',
        'password': 'password'
    }
    
    GIFUROGE_DB_CONFIG = {
        'host': 'postgres-db',
        'port': 5432,
        'database': 'gifuroge',
        'user': 'postgres',
        'password': 'password'
    }
    
    try:
        # データベース接続
        old_conn = psycopg2.connect(**OLD_DB_CONFIG)
        gifuroge_conn = psycopg2.connect(**GIFUROGE_DB_CONFIG)
        
        with transaction.atomic():
            # === STEP 1: ユーザー確認 ===
            print("\n=== STEP 1: ユーザー確認 ===")
            
            admin_user, created = CustomUser.objects.get_or_create(
                username='admin',
                defaults={
                    'email': 'admin@example.com',
                    'is_staff': True,
                    'is_superuser': True
                }
            )
            print(f"管理ユーザー: {'作成' if created else '既存'}")
            
            # === STEP 2: イベントとカテゴリー情報取得 ===
            print("\n=== STEP 2: 既存イベント・カテゴリー確認 ===")
            
            existing_events = list(NewEvent2.objects.values_list('id', 'name'))
            print(f"既存イベント数: {len(existing_events)}件")
            
            if not existing_events:
                print("❌ イベントが存在しません。先にイベントを作成してください。")
                sys.exit(1)
            
            existing_categories = list(NewCategory.objects.values_list('id', 'name'))
            print(f"既存カテゴリー数: {len(existing_categories)}件")
            
            if not existing_categories:
                print("❌ カテゴリーが存在しません。先にカテゴリーを作成してください。")
                sys.exit(1)
            
            # === STEP 3: チーム移行 ===
            print("\n=== STEP 3: チーム移行 ===")
            
            with old_conn.cursor() as cursor:
                cursor.execute("""
                    SELECT id, name, owner_id, event_id, reg_date, 
                           representative_name, representative_phone, 
                           representative_email, is_deleted 
                    FROM team 
                    WHERE is_deleted = FALSE
                    ORDER BY id;
                """)
                old_teams = cursor.fetchall()
            
            print(f"old_rogdbのチーム数: {len(old_teams)}件")
            
            total_migrated_teams = 0
            
            for team_data in old_teams:
                old_team_id, name, owner_id, event_id, reg_date, rep_name, rep_phone, rep_email, is_deleted = team_data
                
                # イベントが存在するかチェック
                if not NewEvent2.objects.filter(id=event_id).exists():
                    continue
                
                # チームが既に存在するかチェック
                if Team.objects.filter(id=old_team_id).exists():
                    continue
                
                try:
                    team = Team.objects.create(
                        id=old_team_id,
                        name=name,
                        owner_id=owner_id or admin_user.id,
                        event_id=event_id,
                        reg_date=reg_date,
                        representative_name=rep_name or name,
                        representative_phone=rep_phone or '',
                        representative_email=rep_email or '',
                        is_deleted=False
                    )
                    total_migrated_teams += 1
                    if total_migrated_teams <= 5:
                        print(f"  チーム作成: {name} (ID: {old_team_id})")
                
                except Exception as e:
                    print(f"  ❌ チーム作成エラー: {name} - {e}")
            
            print(f"✅ チーム移行完了: {total_migrated_teams}件作成")
            
            # === STEP 4: メンバー移行 ===
            print("\n=== STEP 4: メンバー移行 ===")
            
            with old_conn.cursor() as cursor:
                cursor.execute("""
                    SELECT id, team_id, name, kana, is_leader, 
                           phone, email, birthday, gender, si_number, is_deleted 
                    FROM member 
                    WHERE is_deleted = FALSE
                    ORDER BY id;
                """)
                old_members = cursor.fetchall()
            
            print(f"old_rogdbのメンバー数: {len(old_members)}件")
            
            total_migrated_members = 0
            
            for member_data in old_members:
                old_member_id, team_id, name, kana, is_leader, phone, email, birthday, gender, si_number, is_deleted = member_data
                
                # チームが存在するかチェック
                if not Team.objects.filter(id=team_id).exists():
                    continue
                
                # メンバーが既に存在するかチェック
                if Member.objects.filter(id=old_member_id).exists():
                    continue
                
                try:
                    member = Member.objects.create(
                        id=old_member_id,
                        team_id=team_id,
                        name=name,
                        kana=kana or '',
                        is_leader=is_leader or False,
                        phone=phone or '',
                        email=email or '',
                        birthday=birthday,
                        gender=gender or '',
                        si_number=si_number,
                        is_deleted=False
                    )
                    total_migrated_members += 1
                    if total_migrated_members <= 5:
                        print(f"  メンバー作成: {name} (チーム{team_id})")
                
                except Exception as e:
                    print(f"  ❌ メンバー作成エラー: {name} - {e}")
            
            print(f"✅ メンバー移行完了: {total_migrated_members}件作成")
            
            # === STEP 5: エントリー移行 ===
            print("\n=== STEP 5: エントリー移行 ===")
            
            total_migrated_entries = 0
            
            # イベント別にエントリーを移行
            for event_id, event_name in existing_events:
                print(f"\n  📊 {event_name} (ID: {event_id}) のエントリー移行中...")
                
                # カテゴリーを取得（なければデフォルト使用）
                cat_id = existing_categories[0][0] if existing_categories else 1
                
                with old_conn.cursor() as cursor:
                    cursor.execute("""
                        SELECT t.id as team_id, t.name as team_name, t.owner_id,
                               s.zekken_number, s.label, s.is_deleted
                        FROM team t
                        LEFT JOIN start s ON t.id = s.team_id
                        WHERE t.event_id = %s AND t.is_deleted = FALSE
                        ORDER BY t.id;
                    """, [event_id])
                    
                    entries_data = cursor.fetchall()
                    print(f"    対象エントリー数: {len(entries_data)}件")
                    
                    event_migrated_entries = 0
                    
                    for entry_data in entries_data:
                        team_id, team_name, owner_id, zekken, label, is_deleted = entry_data
                        
                        # エントリーが既に存在するかチェック
                        if Entry.objects.filter(team_id=team_id, event_id=event_id).exists():
                            continue
                        
                        try:
                            # チームとイベントの存在確認
                            team_obj = Team.objects.get(id=team_id)
                            event_obj = NewEvent2.objects.get(id=event_id)
                            
                            # Entryオブジェクト作成
                            entry = Entry.objects.create(
                                date=event_obj.start_datetime,
                                category_id=cat_id,
                                event_id=event_id,
                                owner_id=owner_id or admin_user.id,
                                team_id=team_id,
                                is_active=True,
                                zekken_number=int(zekken) if zekken else 0,
                                hasGoaled=False,
                                hasParticipated=False,
                                zekken_label=label or f"{event_name}-{zekken}",
                                is_trial=False,
                                staff_privileges=False,
                                can_access_private_events=False,
                                team_validation_status='approved'
                            )
                            
                            event_migrated_entries += 1
                            total_migrated_entries += 1
                            if event_migrated_entries <= 3:
                                print(f"    エントリー作成: {team_name} - ゼッケン{zekken}")
                            
                        except Team.DoesNotExist:
                            print(f"    ❌ チーム{team_id}が見つかりません: {team_name}")
                        except NewEvent2.DoesNotExist:
                            print(f"    ❌ イベント{event_id}が見つかりません")
                        except Exception as e:
                            print(f"    ❌ エントリー作成エラー: {team_name} - {e}")
                    
                    print(f"  ✅ {event_name}: {event_migrated_entries}件のエントリーを移行")
            
            print(f"\n✅ 全エントリー移行完了: {total_migrated_entries}件作成")
            
            # === STEP 6: GPS情報移行 ===
            print("\n=== STEP 6: GPS情報（通過データ）移行 ===")
            
            with gifuroge_conn.cursor() as gifuroge_cursor:
                # GPS情報データ数確認
                gifuroge_cursor.execute("SELECT COUNT(*) FROM gps_information;")
                gps_total_count = gifuroge_cursor.fetchone()[0]
                print(f"GPS情報総数: {gps_total_count}件")
                
                if gps_total_count > 0:
                    # ロガインDBからteam_idとzekken_numberの対応関係を取得
                    print("\n  📊 チーム-ゼッケン対応表作成中...")
                    team_zekken_map = {}
                    
                    with old_conn.cursor() as old_cursor:
                        old_cursor.execute("""
                            SELECT t.id as team_id, s.zekken_number, t.event_id
                            FROM team t
                            LEFT JOIN start s ON t.id = s.team_id
                            WHERE t.is_deleted = FALSE AND s.zekken_number IS NOT NULL;
                        """)
                        team_zekken_data = old_cursor.fetchall()
                        
                        for team_id, zekken_number, event_id in team_zekken_data:
                            if zekken_number:
                                team_zekken_map[str(zekken_number)] = {
                                    'team_id': team_id,
                                    'event_id': event_id
                                }
                    
                    print(f"  チーム-ゼッケン対応: {len(team_zekken_map)}件")
                    
                    # GPS情報をバッチで移行
                    print("\n  🌍 GPS情報移行中...")
                    
                    # 既存のGPS情報をクリア（必要に応じて）
                    with connection.cursor() as django_cursor:
                        django_cursor.execute("SELECT COUNT(*) FROM gps_checkins;")
                        existing_gps = django_cursor.fetchone()[0]
                        print(f"  既存GPS記録: {existing_gps}件")
                    
                    # GPS情報を取得・移行
                    gifuroge_cursor.execute("""
                        SELECT zekken_number, event_code, cp_number, lattitude, longitude,
                               image_address, image_receipt, image_qr, validate_location,
                               goal_time, late_point, create_at, create_user, update_at,
                               update_user, buy_flag, colabo_company_memo, points
                        FROM gps_information
                        ORDER BY create_at;
                    """)
                    
                    gps_records = gifuroge_cursor.fetchall()
                    print(f"  移行対象GPS記録: {len(gps_records)}件")
                    
                    migrated_gps_count = 0
                    batch_size = 1000
                    
                    with connection.cursor() as django_cursor:
                        for i in range(0, len(gps_records), batch_size):
                            batch = gps_records[i:i+batch_size]
                            print(f"    バッチ {i//batch_size + 1}: {len(batch)}件処理中...")
                            
                            for gps_record in batch:
                                (zekken_number, event_code, cp_number, lattitude, longitude,
                                 image_address, image_receipt, image_qr, validate_location,
                                 goal_time, late_point, create_at, create_user, update_at,
                                 update_user, buy_flag, colabo_company_memo, points) = gps_record
                                
                                # zekken_numberから対応するteam_idを取得
                                team_info = team_zekken_map.get(str(zekken_number))
                                team_id = team_info['team_id'] if team_info else None
                                event_id = team_info['event_id'] if team_info else None
                                
                                try:
                                    # gps_checkinsテーブルに実際の構造に合わせて挿入
                                    django_cursor.execute("""
                                        INSERT INTO gps_checkins (
                                            path_order, zekken_number, event_code, cp_number, 
                                            lattitude, longitude, image_address, image_receipt, 
                                            image_qr, validate_location, goal_time, late_point, 
                                            create_at, create_user, update_at, update_user, 
                                            buy_flag, colabo_company_memo, points, event_id,
                                            team_id, validation_status
                                        ) VALUES (
                                            %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, 
                                            %s, %s, %s, %s, %s, %s, %s, %s, %s, %s,
                                            %s, %s
                                        );
                                    """, [
                                        0,  # path_order（デフォルト値）
                                        str(zekken_number),  # zekken_number
                                        event_code,  # event_code
                                        cp_number,  # cp_number
                                        lattitude,  # lattitude
                                        longitude,  # longitude
                                        image_address,  # image_address
                                        image_receipt,  # image_receipt
                                        bool(image_qr) if image_qr is not None else False,  # image_qr
                                        bool(validate_location) if validate_location is not None else False,  # validate_location
                                        goal_time,  # goal_time
                                        late_point,  # late_point
                                        create_at,  # create_at
                                        create_user,  # create_user
                                        update_at,  # update_at
                                        update_user,  # update_user
                                        bool(buy_flag) if buy_flag is not None else False,  # buy_flag
                                        colabo_company_memo or '',  # colabo_company_memo
                                        points,  # points
                                        event_id,  # event_id
                                        team_id,  # team_id
                                        'pending'  # validation_status（デフォルト値）
                                    ])
                                    migrated_gps_count += 1
                                    
                                except Exception as e:
                                    if migrated_gps_count < 5:  # 最初の5件のエラーのみ表示
                                        print(f"      ❌ GPS記録移行エラー: ゼッケン{zekken_number} - {e}")
                            
                            # バッチごとにコミット
                            connection.commit()
                    
                    print(f"  ✅ GPS情報移行完了: {migrated_gps_count}件作成")
                else:
                    print("  📍 GPS情報が存在しません")
        
        old_conn.close()
        gifuroge_conn.close()
        
        # === 最終確認 ===
        print("\n=== 移行結果確認 ===")
        
        total_teams = Team.objects.count()
        total_members = Member.objects.count()
        total_entries = Entry.objects.count()
        
        # GPS情報確認
        with connection.cursor() as cursor:
            cursor.execute("SELECT COUNT(*) FROM gps_checkins;")
            total_gps = cursor.fetchone()[0]
        
        print(f"総チーム数: {total_teams}件")
        print(f"総メンバー数: {total_members}件")
        print(f"総エントリー数: {total_entries}件")
        print(f"総GPS記録数: {total_gps}件")
        
        # イベント別エントリー統計
        print("\n=== イベント別エントリー統計 ===")
        for event_id, event_name in existing_events[:10]:
            entry_count = Entry.objects.filter(event_id=event_id).count()
            if entry_count > 0:
                print(f"  {event_name}: {entry_count}件")
        
        print("\n🎉 全イベントデータ移行（GPS情報含む）が完了しました！")
        print("🎯 通過審査管理画面で全てのイベントのゼッケン番号が表示され、")
        print("   GPS情報による通過データも利用可能になります。")
        
    except Exception as e:
        print(f"❌ エラーが発生しました: {e}")
        import traceback
        traceback.print_exc()
