import pymysql
import utils
from pymysql.cursors import DictCursor


class MySQLHelper:

    def __init__(self):
        try:
            self.host = utils.get_config_value("mysql.host")
            self.user = utils.get_config_value("mysql.user")
            self.password = utils.get_config_value("mysql.password")
            self.db = utils.get_config_value("mysql.db")
            self.port = int(utils.get_config_value("mysql.port"))
            self.charset = utils.get_config_value("mysql.charset")
            self.connection = None
        except Exception as e:
            utils.get_logger().error(f"加载数据库配置文件失败: {e}")

    def connect(self):
        try:
            self.connection = pymysql.connect(
                host=self.host,
                user=self.user,
                password=self.password,
                db=self.db,
                port=self.port,
                charset=self.charset,
                cursorclass=DictCursor,
            )
            # utils.get_logger().info(f"成功连接到数据库：{self.db}。")
        except pymysql.MySQLError as e:
            utils.get_logger().error(
                f"数据库连接失败: {self.host}:{self.port} {self.db}"
            )
            self.connection = None  # 确保连接失败时设置为 None
            raise Exception(f"连接数据库失败: {e}")

    def disconnect(self):
        if self.connection and self.connection.open:
            self.connection.close()
            # utils.get_logger().info("数据库连接已关闭。")

    def execute_query(self, query, params=None):
        try:
            with self.connection.cursor() as cursor:
                cursor.execute(query, params)
                result = cursor.fetchall()
                return result
        except pymysql.MySQLError as e:
            utils.get_logger().error(f"执行查询时出错：{e}")
            return None

    # def execute_non_query(self, query, params=None):
    #     if isinstance(params, list) and all(isinstance(p, tuple) for p in params):
    #         self.execute_many(query, params)
    #     elif isinstance(params, tuple):
    #         self.execute(query, params)
    #     else:
    #         self.execute(query, (params,))

    # def execute(self, query, params=None):
    #     try:
    #         with self.connection.cursor() as cursor:
    #             cursor.execute(query, params)
    #             self.connection.commit()
    #     except pymysql.MySQLError as e:
    #         utils.get_logger().error(f"执行非查询时出错：{e}")
    #         self.connection.rollback()

    # 修改 execute_non_query 使其返回ID
    def execute_non_query(self, query, params=None):
        if isinstance(params, list) and all(isinstance(p, tuple) for p in params):
            return self.execute_many(query, params)
        elif isinstance(params, tuple):
            return self.execute(query, params)
        else:
            return self.execute(query, (params,))
    def execute(self, query, params=None):
        try:
            with self.connection.cursor() as cursor:
                cursor.execute(query, params)
                self.connection.commit()
                return cursor.lastrowid  # 新增返回自增ID
        except pymysql.MySQLError as e:
            utils.get_logger().error(f"执行非查询时出错：{e}")
            self.connection.rollback()
            return None



    def execute_many(self, query, params: list):
        if isinstance(params, list) and all(isinstance(p, tuple) for p in params):
            try:
                with self.connection.cursor() as cursor:
                    cursor.executemany(query, params)
                    self.connection.commit()
            except pymysql.MySQLError as e:
                utils.get_logger().error(f"执行非查询时出错：{e}")
                self.connection.rollback()
        else:
            raise ValueError("参数必须是元组列表")

    def fetch_one(self, query, params=None):
        try:
            with self.connection.cursor() as cursor:
                cursor.execute(query, params)
                result = cursor.fetchone()
                return result
        except pymysql.MySQLError as e:
            utils.get_logger().error(f"获取一条记录时出错：{e}")
            return None

    def __enter__(self):
        """
        当进入上下文时自动调用此方法。
        它负责建立连接，并将当前实例返回，以便在上下文中使用。

        :return: 返回实例本身，以便在上下文中使用。
        """

        self.connect()  # 建立连接
        return self

    def __exit__(self, exc_type, exc_value, traceback):
        """
        当退出上下文时自动调用此方法。
        无论上下文中的代码是否完成或因异常退出，此方法都会被调用，以确保断开连接。

        :param exc_type: 异常类型, 如果没有异常则为None。
        :param exc_value: 异常值, 如果没有异常则为None。
        :param traceback: 异常的traceback对象, 如果没有异常则为None。
        """
        if exc_type:
            utils.get_logger().error(
                f"数据库发生异常，断开连接。异常类型：{exc_type}, 异常值：{exc_value} traceback: {traceback}"
            )
        self.disconnect()  # 断开连接
