import mysql.connector
from mysql.connector import Error
import numpy as np
import pandas as pd
from yd_api import YDAPI
from api import API
import pandas as pd
from tqdm import tqdm
import time
from datetime import datetime, timedelta
from config import Config
from back_ground_module import CommonModule
import logging
from log_config import configure_task_logger, configure_error_task_logger
import mysql.connector
from mysql.connector import Error
import json

logger = configure_task_logger()

# 获取已经配置好的错误任务日志记录器
error_task_logger = configure_error_task_logger()

# 初始化 API 实例和 Token
yd_api_instance = YDAPI()
api_instance = API()
common_module = CommonModule()
TOKEN = yd_api_instance.generateToken()
print(TOKEN)

# 配置常量
FORMID = "FORM-VJ866081CVI9E7ALB7WOO7BHPPQW25R99AWFL0"  # 分子报备调整
appType = "APP_UYZ0KG6L0CCNV80GZ66O"  # F6客户服务
systemToken = "XA966F81JAJOFCVVVKO64E9MIIZV1EWE5SFMKJ2"  # 密钥

# 数据库配置
DB_CONFIG = Config.HS_DB_Config


class MoleculeReportingAdjustment:
    """分子报备调整"""

    def __init__(self):
        self.molecule_data_list = None
        self.structures = None
        self.denominator_data_list = None
        self.field_map = {
            "归属月份": "dateField_264kcmw",
            "门店编码": "textField_9rqmwyy",
            "门店名称": "textField_oxuvyp2",
            "公司名称": "textField_dqmsvkl",
            "续约后saas版本": "textField_1oil7le",
            "运营负责人": "textField_lxouajj",
            "区域经理": "textField_udayebj",
            "技术专家": "textField_49x98hm",
            "大区": "textField_a4niy40",
            "小区": "textField_s98potv",
            "省份": "textField_526wca0",
            "城市": "textField_pvk89jn",
            "收入类型": "selectField_alb3qo9",
            "关联订单编码": "textField_mtynj7n",
            "调整金额": "numberField_knq1ssd",
            "调整理由说明": "textField_6ysqrxw",
            "总部核对结果": "selectField_lfwb7dnn",
            "分子调整结果": "selectField_lfwb7dno",
            "是否上传衡石": "selectField_mceh174n",
            "总部调整备注": "textField_lfwb7dnp",
        }

    def get_yida_data(self):
        # 获取分母报备数据
        molecule_data = yd_api_instance.read_processes(token=TOKEN, formUuid=FORMID, page=1, n=100,
                                                       appType=appType, systemToken=systemToken)
        self.molecule_data_list = []
        PAGES_two = molecule_data.get('totalCount') // 100 + 1
        for a in range(1, PAGES_two + 1):
            molecule_data = yd_api_instance.read_processes(token=TOKEN, formUuid=FORMID, page=a, n=100,
                                                           appType=appType, systemToken=systemToken)
            for item in molecule_data.get("data", []):

                form_data = item.get("formData", {})
                # Transform the keys using field_map
                transformed_data = {}
                for field_id, value in form_data.items():
                    # Find the display name in field_map
                    for display_name, id_in_map in self.field_map.items():
                        if id_in_map == field_id:
                            transformed_data[display_name] = value
                            break
                # if transformed_data.get("是否上传衡石") == "否" or transformed_data.get("是否上传衡石") is None:
                #     continue
                self.molecule_data_list.append(transformed_data)

    def execute_sql(self, sql, params=None, fetch=False, many=False):
        """执行SQL语句"""
        conn = None
        try:
            conn = mysql.connector.connect(**DB_CONFIG)
            cursor = conn.cursor()
            if many:
                cursor.executemany(sql, params)
            else:
                cursor.execute(sql, params or ())
            conn.commit()
            return cursor.fetchall() if fetch else cursor
        except Error as e:
            error_task_logger.error(f"执行SQL语句时发生错误: {sql}\n错误: {e}")
            task_start_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
            common_module.send_task_error(task_start_time, "分母报备调整", str(e))

            if conn: conn.rollback()
            return None
        finally:
            if conn and conn.is_connected():
                cursor.close()
                conn.close()

    def write_to_bi(self, df):
        # 数据库连接信息
        table_name = "f6_molecule_adjustment"  # 替换为你的实际表名

        # 建立数据库连接
        connection = mysql.connector.connect(
            host=DB_CONFIG["host"],
            user=DB_CONFIG["user"],
            password=DB_CONFIG["password"],
            database=DB_CONFIG["database"]
        )
        cursor = connection.cursor()

        try:
            # 查询表列名
            cursor.execute(f"SHOW COLUMNS FROM {table_name}")
            columns_info = cursor.fetchall()
            db_columns = [col[0] for col in columns_info]  # 提取列名
            df = df.replace([None, np.nan, pd.NA, 'nan', 'NaN', 'NAN', ''], None)
            # 保留 DataFrame 中与数据库列名匹配的列
            filtered_df = df[df.columns.intersection(db_columns)]

            # 如果没有匹配的列，直接返回
            if filtered_df.empty:
                logger.warning("DataFrame 中没有与数据库表结构匹配的列。")
                return

            # 筛选列之后，插入前处理 dict 类型
            filtered_df = filtered_df.copy()
            for col in filtered_df.columns:
                if filtered_df[col].apply(lambda x: isinstance(x, (dict, list)) if x is not None else False).any():
                    filtered_df.loc[:, col] = filtered_df[col].apply(
                        lambda x: json.dumps(x, ensure_ascii=False) if x is not None else x
                    )

            # 构建插入语句
            placeholders = ', '.join(['%s'] * len(filtered_df.columns))
            # 使用反引号避免特殊列明
            columns = ', '.join([f"`{col}`" for col in filtered_df.columns])
            insert_sql = f"INSERT INTO {table_name} ({columns}) VALUES ({placeholders})"

            # 将 DataFrame 写入数据库
            for _, row in filtered_df.iterrows():
                cursor.execute(insert_sql, tuple(row))

            connection.commit()

            logger.info(f"成功写入 {len(filtered_df)} 条记录到 {table_name} 表中。")

        except Exception as e:
            error_task_logger.error(f"写入数据时发生错误: {e}")
            task_start_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
            common_module.send_task_error(task_start_time, "分母报备调整", str(e))

            connection.rollback()
        finally:
            cursor.close()
            connection.close()

    def clear_table(self):
        """清空表数据"""
        if self.execute_sql("TRUNCATE TABLE f6_molecule_adjustment"):
            logger.info(f"成功清空表数据")

    def main(self):
        task_start_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        try:
            logger.info(f"开始执行任务")
            # step1:获取宜搭数据
            self.get_yida_data()
            logger.info(f"获取宜搭数据成功")

            df = pd.DataFrame(self.molecule_data_list)
            if '归属月份' in df.columns:
                # 确保是整数类型
                df['归属月份'] = df['归属月份'].astype('Int64')
                # 转换为datetime对象
                df['归属月份'] = pd.to_datetime(df['归属月份'], unit='ms')
                # 转换为MySQL兼容的字符串格式
                df['归属月份'] = df['归属月份'].dt.strftime('%Y-%m-%d %H:%M:%S')

            # step2:清空BI数据表
            self.clear_table()
            logger.info(f"清空表成功")

            # # step3:写入BI数据库
            self.write_to_bi(df)
            logger.info(f"写入BI数据库成功")

            common_module.send_task_status(task_start_time, "分子报备调整")
        except Exception as e:
            error_task_logger.error(f"任务执行失败: {e}")
            common_module.send_task_error(task_start_time, "分子报备调整", str(e))


if __name__ == '__main__':
    molecule_reporting_adjustment = MoleculeReportingAdjustment()
    molecule_reporting_adjustment.main()
