#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
数据库管理API（异步版本）
"""
import logging
from typing import List

from fastapi import APIRouter, Depends, HTTPException, Query
from sqlalchemy.ext.asyncio import AsyncSession

from app.database import get_db
from core.database_manager.schema import (
    ColumnInfo,
    ConstraintInfo,
    DatabaseConfig,
    DatabaseCreateIn,
    DatabaseInfo,
    DatabaseOperationOut,
    DatabaseRenameIn,
    DataOperationOut,
    DeleteDataIn,
    ExecuteDDLIn,
    ExecuteDDLOut,
    ExecuteSQLIn,
    ExecuteSQLOut,
    IndexInfo,
    InsertDataIn,
    QueryDataIn,
    QueryDataOut,
    SchemaCreateIn,
    SchemaInfo,
    SchemaOperationOut,
    SchemaRenameIn,
    TableInfo,
    TableStructure,
    UpdateDataIn,
    ViewInfo,
    ViewStructure,
)
from core.database_manager.service import (
    AsyncDatabaseManagerService,
    DatabaseManagerForbidden,
    DatabaseManagerValidationError,
)

logger = logging.getLogger(__name__)
router = APIRouter(prefix="/database_manager", tags=["数据库管理"])


async def _get_service(db_name: str, db: AsyncSession) -> AsyncDatabaseManagerService:
    try:
        return await AsyncDatabaseManagerService.create(db_name, db)
    except ValueError as exc:
        raise HTTPException(status_code=404, detail=str(exc)) from exc


def _handle_manager_error(exc: Exception) -> None:
    if isinstance(exc, DatabaseManagerForbidden):
        raise HTTPException(status_code=403, detail=str(exc)) from exc
    if isinstance(exc, DatabaseManagerValidationError):
        raise HTTPException(status_code=400, detail=str(exc)) from exc
    raise exc


# ============ 数据库配置 ============
@router.get("/configs", response_model=List[DatabaseConfig], summary="获取数据库配置列表")
async def get_database_configs(db: AsyncSession = Depends(get_db)):
    """获取所有配置的数据库连接信息"""
    return await AsyncDatabaseManagerService.get_database_configs_async(db)


@router.post("/{db_name}/test", summary="测试数据库连接")
async def test_database_connection(db_name: str, db: AsyncSession = Depends(get_db)):
    """测试指定数据库的连接"""
    service = await _get_service(db_name, db)
    return await service.test_connection()


# ============ 数据库管理 ============
@router.get("/{db_name}/databases", response_model=List[DatabaseInfo], summary="获取数据库列表")
async def get_databases(db_name: str, db: AsyncSession = Depends(get_db)):
    """获取所有数据库"""
    service = await _get_service(db_name, db)
    return await service.get_databases()


@router.post("/{db_name}/databases", response_model=DatabaseOperationOut, summary="创建数据库")
async def create_database(
    db_name: str,
    data: DatabaseCreateIn,
    db: AsyncSession = Depends(get_db),
):
    """创建新数据库"""
    try:
        service = await _get_service(db_name, db)
        success = await service.create_database(
            name=data.name,
            owner=data.owner,
            encoding=data.encoding,
            template=data.template,
            charset=data.charset,
            collation=data.collation,
        )
        return DatabaseOperationOut(
            success=success,
            message="数据库创建成功" if success else "数据库创建失败",
        )
    except HTTPException:
        raise
    except (DatabaseManagerForbidden, DatabaseManagerValidationError) as e:
        _handle_manager_error(e)
    except Exception as e:
        logger.error(f"Failed to create database: {e}")
        return DatabaseOperationOut(success=False, message=str(e))


@router.patch(
    "/{db_name}/databases/{database_name}",
    response_model=DatabaseOperationOut,
    summary="重命名数据库",
)
async def rename_database(
    db_name: str,
    database_name: str,
    data: DatabaseRenameIn,
    db: AsyncSession = Depends(get_db),
):
    """重命名数据库（PostgreSQL / SQL Server）"""
    try:
        service = await _get_service(db_name, db)
        success = await service.rename_database(database_name, data.new_name)
        return DatabaseOperationOut(
            success=success,
            message="数据库重命名成功" if success else "数据库重命名失败",
        )
    except HTTPException:
        raise
    except (DatabaseManagerForbidden, DatabaseManagerValidationError) as e:
        _handle_manager_error(e)
    except Exception as e:
        logger.error(f"Failed to rename database: {e}")
        return DatabaseOperationOut(success=False, message=str(e))


@router.delete("/{db_name}/databases/{database_name}", response_model=DatabaseOperationOut, summary="删除数据库")
async def drop_database(
    db_name: str,
    database_name: str,
    db: AsyncSession = Depends(get_db),
):
    """删除数据库"""
    try:
        service = await _get_service(db_name, db)
        success = await service.drop_database(database_name)
        return DatabaseOperationOut(
            success=success,
            message="数据库删除成功" if success else "数据库删除失败",
        )
    except HTTPException:
        raise
    except (DatabaseManagerForbidden, DatabaseManagerValidationError) as e:
        _handle_manager_error(e)
    except Exception as e:
        logger.error(f"Failed to drop database: {e}")
        return DatabaseOperationOut(success=False, message=str(e))


# ============ Schema管理（PostgreSQL） ============
@router.get("/{db_name}/schemas", response_model=List[SchemaInfo], summary="获取Schema列表")
async def get_schemas(
    db_name: str,
    database: str = None,
    db: AsyncSession = Depends(get_db),
):
    """获取所有Schema（仅PostgreSQL）"""
    service = await _get_service(db_name, db)
    return await service.get_schemas(database)


@router.post("/{db_name}/schemas", response_model=SchemaOperationOut, summary="创建Schema")
async def create_schema(
    db_name: str,
    data: SchemaCreateIn,
    db: AsyncSession = Depends(get_db),
):
    """创建 Schema（PostgreSQL / SQL Server）"""
    try:
        service = await _get_service(db_name, db)
        success = await service.create_schema(data.name, data.database, data.owner)
        return SchemaOperationOut(
            success=success,
            message="Schema 创建成功" if success else "Schema 创建失败",
        )
    except HTTPException:
        raise
    except (DatabaseManagerForbidden, DatabaseManagerValidationError) as e:
        _handle_manager_error(e)
    except Exception as e:
        logger.error(f"Failed to create schema: {e}")
        return SchemaOperationOut(success=False, message=str(e))


@router.delete(
    "/{db_name}/schemas/{schema_name}",
    response_model=SchemaOperationOut,
    summary="删除Schema",
)
async def drop_schema(
    db_name: str,
    schema_name: str,
    database: str = Query(None, description="数据库名"),
    cascade: bool = Query(True, description="是否 CASCADE"),
    db: AsyncSession = Depends(get_db),
):
    """删除 Schema（PostgreSQL / SQL Server）"""
    try:
        service = await _get_service(db_name, db)
        success = await service.drop_schema(schema_name, database, cascade)
        return SchemaOperationOut(
            success=success,
            message="Schema 删除成功" if success else "Schema 删除失败",
        )
    except HTTPException:
        raise
    except (DatabaseManagerForbidden, DatabaseManagerValidationError) as e:
        _handle_manager_error(e)
    except Exception as e:
        logger.error(f"Failed to drop schema: {e}")
        return SchemaOperationOut(success=False, message=str(e))


@router.patch(
    "/{db_name}/schemas/{schema_name}",
    response_model=SchemaOperationOut,
    summary="重命名Schema",
)
async def rename_schema(
    db_name: str,
    schema_name: str,
    data: SchemaRenameIn,
    db: AsyncSession = Depends(get_db),
):
    """重命名 Schema（仅 PostgreSQL）"""
    try:
        service = await _get_service(db_name, db)
        success = await service.rename_schema(schema_name, data.new_name, data.database)
        return SchemaOperationOut(
            success=success,
            message="Schema 重命名成功" if success else "Schema 重命名失败",
        )
    except HTTPException:
        raise
    except (DatabaseManagerForbidden, DatabaseManagerValidationError) as e:
        _handle_manager_error(e)
    except Exception as e:
        logger.error(f"Failed to rename schema: {e}")
        return SchemaOperationOut(success=False, message=str(e))


# ============ 表管理 ============
@router.get("/{db_name}/tables", response_model=List[TableInfo], summary="获取表列表")
async def get_tables(
    db_name: str,
    database: str = Query(None, description="数据库名"),
    schema_name: str = Query(None, description="Schema名"),
    db: AsyncSession = Depends(get_db),
):
    """获取指定schema/database的所有表"""
    service = await _get_service(db_name, db)
    return await service.get_tables(database=database, schema_name=schema_name)


@router.get("/{db_name}/tables/{table_name}/structure", response_model=TableStructure, summary="获取表结构")
async def get_table_structure(
    db_name: str,
    table_name: str,
    database: str = Query(None, description="数据库名"),
    schema_name: str = Query(None, description="Schema名"),
    db: AsyncSession = Depends(get_db),
):
    """获取表的详细结构"""
    service = await _get_service(db_name, db)
    try:
        return await service.get_table_structure(
            table_name, database=database, schema_name=schema_name
        )
    except ValueError as e:
        raise HTTPException(status_code=404, detail=str(e)) from e


@router.get("/{db_name}/tables/{table_name}/ddl", summary="获取表DDL")
async def get_table_ddl(
    db_name: str,
    table_name: str,
    database: str = Query(None, description="数据库名"),
    schema_name: str = Query(None, description="Schema名"),
    db: AsyncSession = Depends(get_db),
):
    """获取表的DDL语句"""
    service = await _get_service(db_name, db)
    ddl = await service.get_table_ddl(table_name, schema_name, database)
    return {"ddl": ddl}


@router.get("/{db_name}/tables/{table_name}/columns", response_model=List[ColumnInfo], summary="获取表字段")
async def get_table_columns(
    db_name: str,
    table_name: str,
    database: str = Query(None, description="数据库名"),
    schema_name: str = Query(None, description="Schema名"),
    db: AsyncSession = Depends(get_db),
):
    """获取表的字段信息"""
    service = await _get_service(db_name, db)
    return await service.get_table_columns(table_name, schema_name, database)


@router.get("/{db_name}/tables/{table_name}/indexes", response_model=List[IndexInfo], summary="获取表索引")
async def get_table_indexes(
    db_name: str,
    table_name: str,
    database: str = Query(None, description="数据库名"),
    schema_name: str = Query(None, description="Schema名"),
    db: AsyncSession = Depends(get_db),
):
    """获取表的索引信息"""
    service = await _get_service(db_name, db)
    return await service.get_table_indexes(table_name, schema_name, database)


@router.get("/{db_name}/tables/{table_name}/constraints", response_model=List[ConstraintInfo], summary="获取表约束")
async def get_table_constraints(
    db_name: str,
    table_name: str,
    database: str = Query(None, description="数据库名"),
    schema_name: str = Query(None, description="Schema名"),
    db: AsyncSession = Depends(get_db),
):
    """获取表的约束信息"""
    service = await _get_service(db_name, db)
    return await service.get_table_constraints(table_name, schema_name, database)


# ============ 视图管理 ============
@router.get("/{db_name}/views", response_model=List[ViewInfo], summary="获取视图列表")
async def get_views(
    db_name: str,
    database: str = Query(None, description="数据库名"),
    schema_name: str = Query(None, description="Schema名"),
    db: AsyncSession = Depends(get_db),
):
    """获取指定schema/database的所有视图"""
    service = await _get_service(db_name, db)
    return await service.get_views(database=database, schema_name=schema_name)


@router.get("/{db_name}/views/{view_name}/structure", response_model=ViewStructure, summary="获取视图结构")
async def get_view_structure(
    db_name: str,
    view_name: str,
    schema_name: str = Query(None, description="Schema名"),
    db: AsyncSession = Depends(get_db),
):
    """获取视图的详细结构"""
    service = await _get_service(db_name, db)
    try:
        return await service.get_view_structure(view_name, schema_name)
    except ValueError as e:
        raise HTTPException(status_code=404, detail=str(e)) from e


@router.get("/{db_name}/views/{view_name}/definition", summary="获取视图定义")
async def get_view_definition(
    db_name: str,
    view_name: str,
    schema_name: str = Query(None, description="Schema名"),
    db: AsyncSession = Depends(get_db),
):
    """获取视图的定义SQL"""
    service = await _get_service(db_name, db)
    definition = await service.get_view_definition(view_name, schema_name)
    return {"definition": definition}


@router.get("/{db_name}/views/{view_name}/dependencies", response_model=List[str], summary="获取视图依赖")
async def get_view_dependencies(
    db_name: str,
    view_name: str,
    schema_name: str = Query(None, description="Schema名"),
    db: AsyncSession = Depends(get_db),
):
    """获取视图依赖的表列表"""
    service = await _get_service(db_name, db)
    return await service.get_view_dependencies(view_name, schema_name)


# ============ 数据查询 ============
@router.post("/{db_name}/query", response_model=QueryDataOut, summary="查询表数据")
async def query_data(
    db_name: str,
    data: QueryDataIn,
    db: AsyncSession = Depends(get_db),
):
    """分页查询表数据"""
    service = await _get_service(db_name, db)
    return await service.query_data(
        table_name=data.table_name,
        schema_name=data.schema_name,
        database=data.database,
        page=data.page,
        page_size=data.page_size,
        where=data.where,
        order_by=data.order_by,
    )


# ============ SQL执行 ============
@router.post("/{db_name}/execute", response_model=ExecuteSQLOut, summary="执行SQL")
async def execute_sql(
    db_name: str,
    data: ExecuteSQLIn,
    db: AsyncSession = Depends(get_db),
):
    """执行自定义SQL语句"""
    service = await _get_service(db_name, db)
    return await service.execute_sql(data.sql, data.is_query)


# ============ 数据操作 ============
@router.post("/{db_name}/data/insert", response_model=DataOperationOut, summary="插入数据")
async def insert_data(
    db_name: str,
    data: InsertDataIn,
    db: AsyncSession = Depends(get_db),
):
    """向表中插入数据"""
    service = await _get_service(db_name, db)
    return await service.insert_data(data.table_name, data.data, data.schema_name)


@router.post("/{db_name}/data/update", response_model=DataOperationOut, summary="更新数据")
async def update_data(
    db_name: str,
    data: UpdateDataIn,
    db: AsyncSession = Depends(get_db),
):
    """更新表中的数据"""
    service = await _get_service(db_name, db)
    return await service.update_data(
        data.table_name, data.data, data.where, data.schema_name
    )


@router.post("/{db_name}/data/delete", response_model=DataOperationOut, summary="删除数据")
async def delete_data(
    db_name: str,
    data: DeleteDataIn,
    db: AsyncSession = Depends(get_db),
):
    """删除表中的数据"""
    service = await _get_service(db_name, db)
    return await service.delete_data(data.table_name, data.where, data.schema_name)


# ============ DDL操作 ============
@router.post("/{db_name}/execute/ddl", response_model=ExecuteDDLOut, summary="执行DDL语句")
async def execute_ddl(
    db_name: str,
    data: ExecuteDDLIn,
    db: AsyncSession = Depends(get_db),
):
    """执行DDL语句（CREATE TABLE, ALTER TABLE, DROP TABLE等）"""
    try:
        service = await _get_service(db_name, db)
        result = await service.execute_ddl(data.sql, data.database, data.schema_name)
        return ExecuteDDLOut(**result)
    except HTTPException:
        raise
    except (DatabaseManagerForbidden, DatabaseManagerValidationError) as e:
        _handle_manager_error(e)
