"""
xll_kit 使用示例
展示 builders 和 executor 的各种用法
"""
import os
from typing import List, Dict, Any

# 设置环境变量（示例）
os.environ['DATABASE_URI'] = 'mysql+pymysql://root:password@localhost:3306/testdb'


# ==================== 示例 1: 基础 Builder 使用 ====================
print("=" * 80)
print("示例 1: Builder 基础使用 - 构建 SQL（不执行）")
print("=" * 80)

from xll_kit.database import MySQLBuilder, PostgreSQLBuilder, SQLBuilderFactory
from sqlalchemy import create_engine, MetaData

# 创建引擎和元数据（用于获取表信息）
engine = create_engine('mysql+pymysql://root:password@localhost:3306/testdb')
metadata = MetaData()
metadata.reflect(bind=engine)

# 假设有一个 users 表
users_table = metadata.tables['users']

# 方式1: 直接使用 Builder
builder = MySQLBuilder()

# 1.1 单条插入
data = {'name': 'Alice', 'email': 'alice@example.com', 'age': 25}
sql_result = builder.build_insert(users_table, data)
print("\n单条插入:")
print(f"SQL: {sql_result.sql}")
print(f"Params: {sql_result.params}")

# 1.2 批量插入
data_list = [
    {'name': 'Bob', 'email': 'bob@example.com', 'age': 30},
    {'name': 'Charlie', 'email': 'charlie@example.com', 'age': 28},
    {'name': 'David', 'email': 'david@example.com', 'age': 35}
]
sql_result = builder.build_batch_insert(users_table, data_list)
print("\n批量插入:")
print(f"SQL: {sql_result.sql[:200]}...")
print(f"Params count: {len(sql_result.params)}")

# 1.3 Upsert（ON DUPLICATE KEY UPDATE）
sql_result = builder.build_upsert(users_table, data, conflict_target=['email'])
print("\nUpsert:")
print(f"SQL: {sql_result.sql}")

# 1.4 单条更新
update_data = {'name': 'Alice Updated', 'age': 26}
where = {'id': 1}
sql_result = builder.build_update(users_table, update_data, where)
print("\n单条更新:")
print(f"SQL: {sql_result.sql}")
print(f"Params: {sql_result.params}")

# 1.5 批量更新
update_list = [
    {'id': 1, 'name': 'Alice V2', 'age': 27},
    {'id': 2, 'name': 'Bob V2', 'age': 31}
]
sql_result = builder.build_batch_update(users_table, update_list, key_columns=['id'])
print("\n批量更新:")
print(f"SQL: {sql_result.sql[:300]}...")

# 1.6 删除
conditions = {'id': 1}
sql_result = builder.build_delete(users_table, conditions)
print("\n删除:")
print(f"SQL: {sql_result.sql}")
print(f"Params: {sql_result.params}")

engine.dispose()


# ==================== 示例 2: 使用 Builder Factory ====================
print("\n" + "=" * 80)
print("示例 2: 使用 Builder Factory - 根据数据库类型自动选择")
print("=" * 80)

# 自动根据数据库类型选择 Builder
mysql_builder = SQLBuilderFactory.get_builder('mysql')
pg_builder = SQLBuilderFactory.get_builder('postgresql')

print(f"\nMySQL Builder: {type(mysql_builder).__name__}")
print(f"PostgreSQL Builder: {type(pg_builder).__name__}")

# PostgreSQL 的 Upsert 语法不同
engine_pg = create_engine('postgresql://user:pass@localhost/testdb')
metadata_pg = MetaData()
# metadata_pg.reflect(bind=engine_pg)  # 需要有真实连接

# 注意：PostgreSQL 使用 ON CONFLICT 语法
# sql_result = pg_builder.build_upsert(table, data, ['email'])
# print(f"\nPostgreSQL Upsert: {sql_result.sql}")


# ==================== 示例 3: Executor 基础使用 ====================
print("\n" + "=" * 80)
print("示例 3: Executor 基础使用 - 构建并执行 SQL")
print("=" * 80)

from xll_kit.database import SQLExecutor

# 创建执行器
executor = SQLExecutor(
    database_uri='mysql+pymysql://root:password@localhost:3306/testdb',
    echo=False  # True 会打印 SQL
)

try:
    # 获取表对象
    table = executor.get_table('users')
    
    # 3.1 执行插入
    print("\n执行插入:")
    builder = MySQLBuilder()
    data = {'name': 'Test User', 'email': 'test@example.com', 'age': 22}
    sql_result = builder.build_insert(table, data)
    affected = executor.execute(sql_result)
    print(f"插入成功，影响行数: {affected}")
    
    # 3.2 执行查询
    print("\n执行查询:")
    results = executor.query(
        "SELECT * FROM users WHERE age > :min_age ORDER BY age DESC LIMIT 5",
        {'min_age': 20}
    )
    print(f"查询结果: {len(results)} 条")
    for row in results[:3]:
        print(f"  - {row}")
    
    # 3.3 查询单条
    print("\n查询单条:")
    user = executor.query_one(
        "SELECT * FROM users WHERE email = :email",
        {'email': 'test@example.com'}
    )
    print(f"单条结果: {user}")
    
finally:
    executor.close()


# ==================== 示例 4: 从环境变量创建 Executor ====================
print("\n" + "=" * 80)
print("示例 4: 从环境变量创建 Executor")
print("=" * 80)

# 方式1: 从环境变量
executor = SQLExecutor.from_env('DATABASE_URI')
print(f"从环境变量创建: {executor.database_uri[:30]}...")
executor.close()

# 方式2: 从配置字典
config = {
    'database_uri': 'mysql+pymysql://root:password@localhost:3306/testdb',
    'echo': False
}
executor = SQLExecutor.from_dict(config)
print(f"从配置字典创建: {executor.database_uri[:30]}...")
executor.close()


# ==================== 示例 5: 批量操作 ====================
print("\n" + "=" * 80)
print("示例 5: 批量操作 - 大数据量处理")
print("=" * 80)

from xll_kit.database import BatchExecutor

executor = SQLExecutor.from_env('DATABASE_URI')
batch_executor = BatchExecutor(executor, batch_size=100)

try:
    # 准备大量数据
    large_data_list = [
        {'name': f'User{i}', 'email': f'user{i}@example.com', 'age': 20 + i % 50}
        for i in range(500)
    ]
    
    # 构建所有 SQL
    builder = MySQLBuilder()
    table = executor.get_table('users')
    
    # 方式1: 一次性批量插入（自动分批）
    print("\n方式1: 一次性大批量插入")
    sql_result = builder.build_batch_insert(table, large_data_list)
    affected = executor.execute(sql_result)
    print(f"插入完成，影响行数: {affected}")
    
    # 方式2: 使用 BatchExecutor 分批执行
    print("\n方式2: 使用 BatchExecutor 分批")
    sql_results = []
    for i in range(0, len(large_data_list), 100):
        batch = large_data_list[i:i+100]
        sql_results.append(builder.build_batch_insert(table, batch))
    
    total_affected = batch_executor.execute_batches(sql_results)
    print(f"分批执行完成，总影响行数: {total_affected}")
    
finally:
    executor.close()


# ==================== 示例 6: Prefect 集成使用 ====================
print("\n" + "=" * 80)
print("示例 6: 在 Prefect 中使用")
print("=" * 80)

print("""
# 在 Prefect Flow 中使用 Builder + Executor

from prefect import task, flow
from xll_kit.database import MySQLBuilder, SQLExecutor

@task(retries=3)
def insert_users(data_list: List[Dict]):
    # 在 Task 内部创建 executor（不跨 Task 共享）
    executor = SQLExecutor.from_env('DATABASE_URI')
    builder = MySQLBuilder()
    
    try:
        table = executor.get_table('users')
        sql_result = builder.build_batch_insert(table, data_list)
        affected = executor.execute(sql_result)
        return affected
    finally:
        executor.close()

@flow
def etl_flow():
    users = [
        {'name': 'Alice', 'email': 'alice@example.com', 'age': 25},
        {'name': 'Bob', 'email': 'bob@example.com', 'age': 30}
    ]
    result = insert_users(users)
    print(f"Inserted {result} rows")

# 运行
etl_flow()
""")


# ==================== 示例 7: 使用预定义的 Prefect Tasks ====================
print("\n" + "=" * 80)
print("示例 7: 使用 xll_kit 预定义的 Prefect Tasks")
print("=" * 80)

print("""
from prefect import flow
from xll_kit.prefect_integration import (
    insert_data_task,
    batch_insert_task,
    upsert_task,
    query_task
)

@flow
def data_processing_flow():
    database_uri = "mysql+pymysql://root:password@localhost/testdb"
    
    # 1. 插入单条数据
    insert_data_task(
        database_uri=database_uri,
        table_name='users',
        data={'name': 'Alice', 'email': 'alice@example.com', 'age': 25}
    )
    
    # 2. 批量插入
    users = [
        {'name': 'Bob', 'email': 'bob@example.com', 'age': 30},
        {'name': 'Charlie', 'email': 'charlie@example.com', 'age': 28}
    ]
    batch_insert_task(
        database_uri=database_uri,
        table_name='users',
        data_list=users,
        batch_size=100
    )
    
    # 3. Upsert
    upsert_task(
        database_uri=database_uri,
        table_name='users',
        data_list=users,
        conflict_target=['email']  # 冲突时更新
    )
    
    # 4. 查询
    results = query_task(
        database_uri=database_uri,
        sql="SELECT * FROM users WHERE age > :min_age",
        params={'min_age': 25}
    )
    print(f"Found {len(results)} users")

# 运行
data_processing_flow()
""")


# ==================== 示例 8: 完整的 ETL 示例 ====================
print("\n" + "=" * 80)
print("示例 8: 完整的 ETL 流程示例")
print("=" * 80)

def etl_example():
    """完整的 ETL 流程示例"""
    from xll_kit.database import MySQLBuilder, SQLExecutor
    
    # 1. Extract - 从源数据库提取
    source_executor = SQLExecutor(
        'mysql+pymysql://root:password@localhost:3306/source_db'
    )
    
    try:
        print("\n1. Extract - 提取数据")
        source_data = source_executor.query(
            "SELECT id, name, email, age FROM source_users WHERE active = :active",
            {'active': 1}
        )
        print(f"提取了 {len(source_data)} 条数据")
        
        # 2. Transform - 数据转换
        print("\n2. Transform - 转换数据")
        transformed_data = []
        for row in source_data:
            transformed_data.append({
                'user_id': row['id'],
                'full_name': row['name'].upper(),
                'email': row['email'].lower(),
                'age_group': 'young' if row['age'] < 30 else 'adult',
                'sync_time': '2024-01-01 00:00:00'
            })
        print(f"转换了 {len(transformed_data)} 条数据")
        
        # 3. Load - 加载到目标数据库
        print("\n3. Load - 加载数据")
        target_executor = SQLExecutor(
            'mysql+pymysql://root:password@localhost:3306/target_db'
        )
        
        try:
            builder = MySQLBuilder()
            table = target_executor.get_table('target_users')
            
            # 使用 Upsert 避免重复
            sql_result = builder.build_batch_upsert(
                table, 
                transformed_data, 
                conflict_target=['user_id']
            )
            affected = target_executor.execute(sql_result)
            print(f"加载完成，影响 {affected} 行")
            
        finally:
            target_executor.close()
            
    finally:
        source_executor.close()

# 运行 ETL
print("\nETL 流程示例代码:")
print(etl_example.__doc__)


# ==================== 示例 9: 错误处理 ====================
print("\n" + "=" * 80)
print("示例 9: 错误处理")
print("=" * 80)

from xll_kit.database.exceptions import (
    DatabaseError,
    SQLBuilderError,
    ExecutionError,
    TableNotFoundError
)

def error_handling_example():
    """错误处理示例"""
    executor = SQLExecutor.from_env('DATABASE_URI')
    
    try:
        # 1. 表不存在
        try:
            table = executor.get_table('non_existent_table')
        except TableNotFoundError as e:
            print(f"\n捕获表不存在错误: {e}")
        
        # 2. SQL 执行错误
        try:
            executor.query("SELECT * FROM invalid_syntax WHERE")
        except ExecutionError as e:
            print(f"\n捕获SQL执行错误: {e}")
            print(f"SQL: {e.sql[:50] if e.sql else 'N/A'}")
        
        # 3. 数据验证错误
        try:
            builder = MySQLBuilder()
            table = executor.get_table('users')
            sql_result = builder.build_batch_insert(table, [])  # 空列表
        except (ValueError, SQLBuilderError) as e:
            print(f"\n捕获数据验证错误: {e}")
        
    finally:
        executor.close()

error_handling_example()


# ==================== 示例 10: 性能优化技巧 ====================
print("\n" + "=" * 80)
print("示例 10: 性能优化技巧")
print("=" * 80)

print("""
性能优化建议：

1. 批量操作
   - 使用 build_batch_insert 代替循环调用 build_insert
   - 批次大小建议：1000-5000 条
   
   # ❌ 不推荐
   for data in data_list:
       sql = builder.build_insert(table, data)
       executor.execute(sql)
   
   # ✅ 推荐
   sql = builder.build_batch_insert(table, data_list)
   executor.execute(sql)

2. 连接池配置
   # 在 DatabaseManager 中使用连接池
   from xll_kit import DatabaseManager
   
   db = DatabaseManager(
       database_uri='...',
       pool_size=10,        # 连接池大小
       max_overflow=20,     # 最大溢出
       pool_timeout=30      # 超时时间
   )

3. 事务批量提交
   # 使用上下文管理器确保事务
   with executor.get_connection() as conn:
       for sql_result in sql_results:
           conn.execute(text(sql_result.sql), sql_result.params)
       conn.commit()  # 一次提交

4. Prefect 中避免状态共享
   # ❌ 不推荐：跨 Task 共享 executor
   executor = SQLExecutor(...)
   
   @task
   def task1():
       executor.execute(...)  # 有状态，不可序列化
   
   # ✅ 推荐：每个 Task 内部创建
   @task
   def task1():
       executor = SQLExecutor.from_env()
       try:
           executor.execute(...)
       finally:
           executor.close()

5. 大数据量分批处理
   # 使用 BatchExecutor
   from xll_kit.database import BatchExecutor
   
   batch_executor = BatchExecutor(executor, batch_size=1000)
   batch_executor.execute_batches(sql_results)
""")


# ==================== 使用总结 ====================
print("\n" + "=" * 80)
print("使用总结")
print("=" * 80)

print("""
📦 xll_kit 三层架构：

1. Builder 层（纯函数，构建SQL）
   - MySQLBuilder / PostgreSQLBuilder
   - 输入：Table + Data
   - 输出：SQLResult (sql + params)
   - 特点：无状态，可序列化，适合 Prefect

2. Executor 层（轻量执行）
   - SQLExecutor：轻量级执行器
   - BatchExecutor：批量执行器
   - 特点：适合 Prefect Task，每次创建新实例

3. Manager 层（完整功能）
   - DatabaseManager：完整 CRUD
   - 特点：有状态，连接池，不适合跨 Prefect Task

🎯 使用场景选择：

场景                    推荐方案
─────────────────────────────────────────
Prefect Flow         → Builder + Executor
FastAPI 应用         → DatabaseManager
批处理脚本           → DatabaseManager
定时任务             → Builder + Executor
复杂 ETL            → Builder + Executor

📝 最佳实践：

1. Prefect 中每个 Task 创建新的 Executor
2. 使用参数化查询（自动防SQL注入）
3. 批量操作优于循环单条操作
4. 适当配置连接池大小
5. 使用日志追踪执行情况
""")