import asyncio
import aiomysql
import asyncpg
from datetime import datetime
from zoneinfo import ZoneInfo
import os
from dotenv import load_dotenv

load_dotenv()

# MySQL connection settings
MYSQL_USER = os.getenv("MYSQL_USER", "bot")
MYSQL_PASSWORD = os.getenv("MYSQL_PASSWORD", "secret")
MYSQL_HOST = os.getenv("MYSQL_HOST", "localhost")
MYSQL_PORT = os.getenv("MYSQL_PORT", "3306")
MYSQL_DATABASE = os.getenv("MYSQL_DATABASE", "vpn_shop")

# PostgreSQL connection settings
POSTGRES_USER = os.getenv("POSTGRES_USER", "bot")
POSTGRES_PASSWORD = os.getenv("POSTGRES_PASSWORD", "secret")
POSTGRES_HOST = os.getenv("POSTGRES_HOST", "localhost")
POSTGRES_PORT = os.getenv("POSTGRES_PORT", "5432")
POSTGRES_DATABASE = os.getenv("POSTGRES_DATABASE", "vpn_shop")

async def check_postgres_tables_exist(conn):
    """Check if all required tables exist in PostgreSQL"""
    tables = ['users', 'vpn_plans', 'vpn_subscriptions', 'payments', 'orders']
    for table in tables:
        result = await conn.fetchval(
            "SELECT EXISTS (SELECT FROM information_schema.tables WHERE table_name = $1)",
            table
        )
        if not result:
            raise Exception(f"Table '{table}' does not exist in PostgreSQL. Please run init_postgres.py first.")

async def migrate_data():
    print("Starting migration from MySQL to PostgreSQL...")
    
    # Connect to PostgreSQL first to check tables
    postgres_conn = await asyncpg.connect(
        host=POSTGRES_HOST,
        port=int(POSTGRES_PORT),
        user=POSTGRES_USER,
        password=POSTGRES_PASSWORD,
        database=POSTGRES_DATABASE
    )

    try:
        # Check if tables exist
        print("Checking if PostgreSQL tables exist...")
        await check_postgres_tables_exist(postgres_conn)
        print("All required tables found in PostgreSQL!")

        # Connect to MySQL database
        print("Connecting to MySQL database...")
        mysql_conn = await aiomysql.connect(
            host=MYSQL_HOST,
            port=int(MYSQL_PORT),
            user=MYSQL_USER,
            password=MYSQL_PASSWORD,
            db=MYSQL_DATABASE,
            autocommit=True
        )
        mysql_cur = await mysql_conn.cursor()
        
        try:
            # Migrate users
            print("Migrating users...")
            await mysql_cur.execute("SELECT * FROM users")
            users = await mysql_cur.fetchall()
            if users:
                # Get column names
                columns = [desc[0] for desc in mysql_cur.description]
                for user in users:
                    user_dict = dict(zip(columns, user))
                    await postgres_conn.execute(
                        "INSERT INTO users (telegram_id, username, created_at, ban, ref_id, balance) "
                        "VALUES ($1, $2, $3, $4, $5, $6) ON CONFLICT (telegram_id) DO NOTHING",
                        user_dict['telegram_id'],
                        user_dict['username'],
                        user_dict['created_at'],
                        bool(user_dict['ban']),
                        user_dict['ref_id'],
                        user_dict['balance']
                    )
            print(f"Migrated {len(users)} users")
            
            # Migrate VPN plans
            print("Migrating VPN plans...")
            await mysql_cur.execute("SELECT * FROM vpn_plans")
            plans = await mysql_cur.fetchall()
            if plans:
                columns = [desc[0] for desc in mysql_cur.description]
                for plan in plans:
                    plan_dict = dict(zip(columns, plan))
                    await postgres_conn.execute(
                        "INSERT INTO vpn_plans (id, name, duration_days, price, description) "
                        "VALUES ($1, $2, $3, $4, $5) ON CONFLICT (id) DO NOTHING",
                        plan_dict['id'],
                        plan_dict['name'],
                        plan_dict['duration_days'],
                        plan_dict['price'],
                        plan_dict['description']
                    )
            print(f"Migrated {len(plans)} VPN plans")
            
            # Migrate VPN subscriptions
            print("Migrating VPN subscriptions...")
            await mysql_cur.execute("SELECT * FROM vpn_subscriptions")
            subscriptions = await mysql_cur.fetchall()
            if subscriptions:
                columns = [desc[0] for desc in mysql_cur.description]
                for sub in subscriptions:
                    sub_dict = dict(zip(columns, sub))
                    await postgres_conn.execute(
                        "INSERT INTO vpn_subscriptions "
                        "(id, user_id, config_data, start_date, end_date, plan_id, server_name, status) "
                        "VALUES ($1, $2, $3, $4, $5, $6, $7, $8) ON CONFLICT (id) DO NOTHING",
                        sub_dict['id'],
                        sub_dict['user_id'],
                        sub_dict['config_data'],
                        sub_dict['start_date'],
                        sub_dict['end_date'],
                        sub_dict['plan_id'],
                        sub_dict['server_name'],
                        sub_dict['status']
                    )
            print(f"Migrated {len(subscriptions)} VPN subscriptions")
            
            # Migrate payments
            print("Migrating payments...")
            await mysql_cur.execute("SELECT * FROM payments")
            payments = await mysql_cur.fetchall()
            if payments:
                columns = [desc[0] for desc in mysql_cur.description]
                for payment in payments:
                    payment_dict = dict(zip(columns, payment))
                    await postgres_conn.execute(
                        "INSERT INTO payments "
                        "(id, user_id, amount, payment_id, status, provider, created_at, paid_at) "
                        "VALUES ($1, $2, $3, $4, $5, $6, $7, $8) ON CONFLICT (id) DO NOTHING",
                        payment_dict['id'],
                        payment_dict['user_id'],
                        payment_dict['amount'],
                        payment_dict['payment_id'],
                        payment_dict['status'],
                        payment_dict.get('provider', 'unknown'),  # Handle missing provider column
                        payment_dict['created_at'],
                        payment_dict['paid_at']
                    )
            print(f"Migrated {len(payments)} payments")
            
            # Migrate orders (if table exists)
            print("Migrating orders...")
            try:
                await mysql_cur.execute("SELECT * FROM orders")
                orders = await mysql_cur.fetchall()
                if orders:
                    columns = [desc[0] for desc in mysql_cur.description]
                    for order in orders:
                        order_dict = dict(zip(columns, order))
                        await postgres_conn.execute(
                            "INSERT INTO orders "
                            "(id, user_id, amount, created_at, type_of_order, product, product_info) "
                            "VALUES ($1, $2, $3, $4, $5, $6, $7) ON CONFLICT (id) DO NOTHING",
                            order_dict['id'],
                            order_dict['user_id'],
                            order_dict['amount'],
                            order_dict['created_at'],
                            order_dict['type_of_order'],
                            order_dict['product'],
                            order_dict['product_info']
                        )
                print(f"Migrated {len(orders)} orders")
            except Exception as e:
                print(f"Orders table not found or error migrating orders: {e}")
            
            print("Migration completed successfully!")
            
        except Exception as e:
            print(f"Error during migration: {e}")
            raise
        finally:
            await mysql_cur.close()
            mysql_conn.close()
                
    except Exception as e:
        print(f"Error: {e}")
        raise
    finally:
        await postgres_conn.close()

if __name__ == "__main__":
    asyncio.run(migrate_data()) 