import mysql.connector
import numpy as np
from yd_api import YDAPI
from api import API
import pandas as pd
from datetime import datetime
from config import Config
from back_ground_module import CommonModule
from log_config import configure_task_logger, configure_error_task_logger
import mysql.connector
from mysql.connector import Error
import re
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()

# 配置常量
FORMID = "FORM-WV866IC119W8BZC7AKHAR7VT3FI52W4Q1VBFLD1"  # FPO需求提交
appType = "APP_UYZ0KG6L0CCNV80GZ66O"  # F6客户服务
systemToken = "XA966F81JAJOFCVVVKO64E9MIIZV1EWE5SFMKJ2"  # 密钥
BASE_URL = "https://f6car.aliwork.com"  # 基础URL
DB_CONFIG = Config.HS_DB_Config


# 数据库配置


class DenominatorReportingAdjustment:
    """分母报备调整"""

    def __init__(self):
        self.structures = None
        self.denominator_data_list = None
        self.field_map = {
            "门店编码": "textField_pl5p5a3",
            "门店名称": "textField_fcl5xg6",
            "公司名称": "textField_bdlfhio",
            "大区": "textField_urgu3fr",
            "小区": "textField_dro2c5y",
            "战区": "textField_e3pkxp1",
            "技术专家": "employeeField_mca5shp0",
            "区域客成": "employeeField_mca5shp1",
            "运营负责人": "textField_j9uxos9",
            "SaaS版本": "textField_0hbyovw",
            "开户日期": "dateField_dnj8hop",
            "开始时间": "dateField_ppr0d3a",
            "结束时间": "dateField_jvsr6ef",
            "原分母金额": "numberField_l4bcg80",
            "调整后金额": "numberField_9bjyfzj",
            "分母调整理由": "textField_niczt1b",
            "对应订单编码": "textField_2ubszzt",
            "转养车后门店编码": "textField_q14ebff",
            "总部调整备注": "textareaField_lfrnbtbu",
            "总部调整结果": "selectField_lfqwg05y",
            "总部核对结果": "selectField_lfqwg05x",
            "是否上传衡石": "selectField_mca5shoz",
            "是否计入应续约数": "selectField_mdnwwvyo"
        }

    def get_yida_data(self):
        # 获取分母报备数据
        denominator_data = yd_api_instance.read_processes(token=TOKEN, formUuid=FORMID, page=1, n=100,
                                                          appType=appType, systemToken=systemToken)
        self.denominator_data_list = []

        PAGES_two = denominator_data.get('totalCount') // 100 + 1
        parentheses_pattern = re.compile(r'$[^)]*$')
        for a in range(1, PAGES_two + 1):
            denominator_data = yd_api_instance.read_processes(token=TOKEN, formUuid=FORMID, page=a, n=100,
                                                              appType=appType, systemToken=systemToken)
            for item in denominator_data.get("data", []):
                form_data = item.get("formData", {})
                # Transform the keys using field_map
                transformed_data = {}
                for field_key in ['employeeField_mca5shp1', 'employeeField_mca5shp0']:
                    if field_key in form_data and isinstance(form_data[field_key], list) and len(
                            form_data[field_key]) > 0:
                        # 取第一个元素
                        raw_value = form_data[field_key][0]
                        # 去除括号及其中的内容
                        cleaned_value = parentheses_pattern.sub('', raw_value).strip()
                        # 更新 formData 中的值
                        form_data[field_key] = cleaned_value

                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
                # print(transformed_data.get("是否上传衡石"))
                # if transformed_data.get("是否上传衡石") == "否" or transformed_data.get("是否上传衡石") is None:
                #     continue
                self.denominator_data_list.append(transformed_data)

    def execute_sql(self, sql, params=None, fetch=False, many=False):
        """执行SQL语句"""
        global cursor
        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}\n错误: {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_denominator_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]  # 提取列名


            # 处理日期字段 - 新增部分
            date_fields = ['开户日期', '开始时间', '结束时间']
            for field in date_fields:
                if field in df.columns:
                    # 转换为整数类型
                    df[field] = pd.to_numeric(df[field], errors='coerce').astype('Int64')
                    # 转换为datetime对象
                    df[field] = pd.to_datetime(df[field], unit='ms')
                    # 转换为MySQL兼容的字符串格式
                    df[field] = df[field].dt.strftime('%Y-%m-%d %H:%M:%S')

            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_denominator_adjustment"):
            logger.info("✅ 清空表数据成功")

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

            df = pd.DataFrame(self.denominator_data_list)

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

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

            common_module.send_task_status(task_start_time, "分母报备调整")
        except Exception as e:
            error_task_logger.error("分母报备调整失败")
            common_module.send_task_error(task_start_time, "分母报备调整", str(e))


if __name__ == '__main__':
    denominator_reporting_adjustment = DenominatorReportingAdjustment()
    denominator_reporting_adjustment.main()
