"""
数据库操作模块
数据库连接和操作辅助
"""
import sqlite3
import json
from typing import Optional, List, Dict, Any, Union
from pathlib import Path
from loguru import logger
from dataclasses import dataclass
from contextlib import contextmanager


@dataclass
class DatabaseConfig:
    """数据库配置"""
    type: str = "sqlite"  # sqlite, mysql, postgresql
    path: str = ":memory:"  # sqlite路径
    host: str = "localhost"
    port: int = 3306
    database: str = ""
    user: str = ""
    password: str = ""


class DatabaseManager:
    """
    数据库管理器
    提供简化的数据库操作接口
    """
    
    def __init__(self, config: DatabaseConfig):
        self.config = config
        self._connection: Optional[sqlite3.Connection] = None
    
    def connect(self):
        """连接数据库"""
        if self.config.type == "sqlite":
            self._connection = sqlite3.connect(self.config.path)
            self._connection.row_factory = sqlite3.Row
            logger.info(f"SQLite数据库已连接: {self.config.path}")
        else:
            # 其他数据库类型需要额外的库
            raise NotImplementedError(f"暂不支持 {self.config.type}")
    
    def close(self):
        """关闭连接"""
        if self._connection:
            self._connection.close()
            self._connection = None
            logger.info("数据库连接已关闭")
    
    @contextmanager
    def connection(self):
        """连接上下文管理器"""
        self.connect()
        try:
            yield self
        finally:
            self.close()
    
    def execute(
        self,
        sql: str,
        params: tuple = None,
    ) -> sqlite3.Cursor:
        """
        执行SQL
        
        Args:
            sql: SQL语句
            params: 参数
            
        Returns:
            Cursor: 游标
        """
        if not self._connection:
            self.connect()
        
        cursor = self._connection.cursor()
        
        if params:
            cursor.execute(sql, params)
        else:
            cursor.execute(sql)
        
        self._connection.commit()
        return cursor
    
    def executemany(
        self,
        sql: str,
        params_list: List[tuple],
    ) -> sqlite3.Cursor:
        """批量执行SQL"""
        if not self._connection:
            self.connect()
        
        cursor = self._connection.cursor()
        cursor.executemany(sql, params_list)
        self._connection.commit()
        
        return cursor
    
    def fetchone(self, sql: str, params: tuple = None) -> Optional[Dict]:
        """查询单条"""
        cursor = self.execute(sql, params)
        row = cursor.fetchone()
        
        if row:
            return dict(row)
        return None
    
    def fetchall(self, sql: str, params: tuple = None) -> List[Dict]:
        """查询多条"""
        cursor = self.execute(sql, params)
        rows = cursor.fetchall()
        
        return [dict(row) for row in rows]
    
    def fetchvalue(self, sql: str, params: tuple = None) -> Any:
        """查询单个值"""
        result = self.fetchone(sql, params)
        if result:
            return list(result.values())[0]
        return None
    
    # ==================== 表操作 ====================
    
    def create_table(
        self,
        table_name: str,
        columns: Dict[str, str],
        if_not_exists: bool = True,
    ):
        """
        创建表
        
        Args:
            table_name: 表名
            columns: 列定义 {列名: 类型}
            if_not_exists: 是否添加IF NOT EXISTS
        """
        cols_def = ", ".join(f"{name} {type_}" for name, type_ in columns.items())
        
        if if_not_exists:
            sql = f"CREATE TABLE IF NOT EXISTS {table_name} ({cols_def})"
        else:
            sql = f"CREATE TABLE {table_name} ({cols_def})"
        
        self.execute(sql)
        logger.info(f"表已创建: {table_name}")
    
    def drop_table(self, table_name: str, if_exists: bool = True):
        """删除表"""
        if if_exists:
            sql = f"DROP TABLE IF EXISTS {table_name}"
        else:
            sql = f"DROP TABLE {table_name}"
        
        self.execute(sql)
        logger.info(f"表已删除: {table_name}")
    
    def table_exists(self, table_name: str) -> bool:
        """检查表是否存在"""
        sql = "SELECT name FROM sqlite_master WHERE type='table' AND name=?"
        result = self.fetchone(sql, (table_name,))
        return result is not None
    
    def get_table_columns(self, table_name: str) -> List[str]:
        """获取表的列名"""
        sql = f"PRAGMA table_info({table_name})"
        rows = self.fetchall(sql)
        return [row['name'] for row in rows]
    
    # ==================== CRUD操作 ====================
    
    def insert(
        self,
        table_name: str,
        data: Dict[str, Any],
    ) -> int:
        """
        插入数据
        
        Args:
            table_name: 表名
            data: 数据字典
            
        Returns:
            int: 插入行的ID
        """
        columns = ", ".join(data.keys())
        placeholders = ", ".join("?" * len(data))
        values = tuple(data.values())
        
        sql = f"INSERT INTO {table_name} ({columns}) VALUES ({placeholders})"
        cursor = self.execute(sql, values)
        
        logger.debug(f"插入数据: {table_name}, id={cursor.lastrowid}")
        return cursor.lastrowid
    
    def insert_many(
        self,
        table_name: str,
        data_list: List[Dict[str, Any]],
    ):
        """批量插入"""
        if not data_list:
            return
        
        columns = ", ".join(data_list[0].keys())
        placeholders = ", ".join("?" * len(data_list[0]))
        values_list = [tuple(d.values()) for d in data_list]
        
        sql = f"INSERT INTO {table_name} ({columns}) VALUES ({placeholders})"
        self.executemany(sql, values_list)
        
        logger.debug(f"批量插入: {table_name}, {len(data_list)}条")
    
    def update(
        self,
        table_name: str,
        data: Dict[str, Any],
        where: str,
        where_params: tuple = None,
    ) -> int:
        """
        更新数据
        
        Args:
            table_name: 表名
            data: 更新数据
            where: WHERE条件
            where_params: WHERE参数
            
        Returns:
            int: 影响行数
        """
        set_clause = ", ".join(f"{k} = ?" for k in data.keys())
        values = tuple(data.values())
        
        if where_params:
            values = values + where_params
        
        sql = f"UPDATE {table_name} SET {set_clause} WHERE {where}"
        cursor = self.execute(sql, values)
        
        logger.debug(f"更新数据: {table_name}, 影响{cursor.rowcount}行")
        return cursor.rowcount
    
    def delete(
        self,
        table_name: str,
        where: str,
        where_params: tuple = None,
    ) -> int:
        """删除数据"""
        sql = f"DELETE FROM {table_name} WHERE {where}"
        cursor = self.execute(sql, where_params)
        
        logger.debug(f"删除数据: {table_name}, 影响{cursor.rowcount}行")
        return cursor.rowcount
    
    def select(
        self,
        table_name: str,
        columns: str = "*",
        where: str = None,
        where_params: tuple = None,
        order_by: str = None,
        limit: int = None,
    ) -> List[Dict]:
        """查询数据"""
        sql = f"SELECT {columns} FROM {table_name}"
        
        if where:
            sql += f" WHERE {where}"
        
        if order_by:
            sql += f" ORDER BY {order_by}"
        
        if limit:
            sql += f" LIMIT {limit}"
        
        return self.fetchall(sql, where_params)
    
    def count(
        self,
        table_name: str,
        where: str = None,
        where_params: tuple = None,
    ) -> int:
        """计数"""
        sql = f"SELECT COUNT(*) FROM {table_name}"
        
        if where:
            sql += f" WHERE {where}"
        
        return self.fetchvalue(sql, where_params)
    
    # ==================== 工具方法 ====================
    
    def execute_script(self, script: str):
        """执行SQL脚本"""
        if not self._connection:
            self.connect()
        
        self._connection.executescript(script)
        logger.info("SQL脚本执行完成")
    
    def backup(self, backup_path: str):
        """备份数据库"""
        if self.config.type != "sqlite":
            raise NotImplementedError("仅支持SQLite备份")
        
        backup_conn = sqlite3.connect(backup_path)
        self._connection.backup(backup_conn)
        backup_conn.close()
        
        logger.info(f"数据库已备份: {backup_path}")
    
    def import_json(
        self,
        table_name: str,
        json_path: str,
    ):
        """从JSON导入数据"""
        with open(json_path, 'r', encoding='utf-8') as f:
            data = json.load(f)
        
        if isinstance(data, list):
            self.insert_many(table_name, data)
        else:
            self.insert(table_name, data)
        
        logger.info(f"JSON数据已导入: {table_name}")
    
    def export_json(
        self,
        table_name: str,
        json_path: str,
        where: str = None,
    ):
        """导出数据到JSON"""
        data = self.select(table_name, where=where)
        
        with open(json_path, 'w', encoding='utf-8') as f:
            json.dump(data, f, ensure_ascii=False, indent=2)
        
        logger.info(f"数据已导出: {json_path}")


# 快捷函数
def create_sqlite_db(path: str = ":memory:") -> DatabaseManager:
    """创建SQLite数据库"""
    config = DatabaseConfig(type="sqlite", path=path)
    return DatabaseManager(config)
