import pandas as pd
import os
import sys

from docx import Document
from copy import deepcopy
from docx.enum.text import WD_COLOR_INDEX
from docx.shared import RGBColor, Pt
from xiaokang.常用 import 时间_文件_分


def 提取块核心样式(run):
    """
    提取run的核心样式特征（新增背景色），用于判断是否相同
    :param run: run对象
    :return: 包含样式特征的字典
    """
    # 提取背景色（高亮色）：优先取RGB值，无则取枚举值，都无则为None
    bg_color = None
    if run.font.highlight_color:
        # 处理枚举类型的背景色（如红色、黄色等）
        if isinstance(run.font.highlight_color, WD_COLOR_INDEX):
            bg_color = run.font.highlight_color.name  # 转为字符串（如"YELLOW"）
        # 部分场景下背景色是RGB值（较少见，兼容处理）
        elif hasattr(run.font.highlight_color, 'rgb'):
            bg_color = run.font.highlight_color.rgb

    return {
        "bold": run.bold,
        "italic": run.italic,
        "font_size": run.font.size,
        "font_color": run.font.color.rgb if run.font.color else None,
        "underline": run.underline,
        "font_name": run.font.name,
        "bg_color": bg_color  # 新增：文本背景色（高亮色）
    }


def 合并样式相同块(paragraph):
    """
    合并段落中样式相同的相邻run，保留不同样式的run
    :param paragraph: 要处理的段落对象
    """
    if len(paragraph.runs) <= 1:
        return paragraph  # 只有1个run，无需合并

    # 步骤1：按样式分组，合并同组文本
    style_groups = []
    # 初始化第一个分组
    first_run = paragraph.runs[0]
    current_style = 提取块核心样式(first_run)
    current_text = first_run.text

    # 遍历剩余run，分组合并
    for run in paragraph.runs[1:]:
        run_style = 提取块核心样式(run)
        # 判断当前run样式是否与上一个分组一致（字典相等则样式相同）
        if run_style == current_style:
            current_text += run.text  # 合并文本
        else:
            # 样式不同，保存当前分组，新建分组
            style_groups.append({"style": current_style, "text": current_text})
            current_style = run_style
            current_text = run.text
    # 保存最后一个分组
    style_groups.append({"style": current_style, "text": current_text})

    # 步骤2：清空原段落的所有run（从后往前删，避免索引错乱）
    for run in reversed(paragraph.runs):
        paragraph._element.remove(run._element)

    # 步骤3：重新添加合并后的run，恢复原样式
    for group in style_groups:
        new_run = paragraph.add_run(group["text"])
        # 应用原样式
        style = group["style"]
        new_run.bold = style["bold"]
        new_run.italic = style["italic"]
        new_run.underline = style["underline"]
        new_run.font.size = style["font_size"]
        new_run.font.name = style["font_name"]
        if style["font_color"]:
            new_run.font.color.rgb = style["font_color"]

    return paragraph


def 读docx(文件路径):
    """
    读取docx文件，返回文档对象
    """
    try:
        doc = Document(文件路径)

        for f1 in doc.paragraphs:
            合并样式相同块(f1)

        for f1 in doc.tables:  # 全表格
            for f2 in f1._cells:  # 每个单元格
                for f3 in f2.paragraphs:  # 每个单元格中的段落
                    合并样式相同块(f3)

        return doc
    except Exception as e:
        print("读取docx文件出错：", e)
        return None


def 读xlsx(文件路径):
    try:
        df = pd.read_excel(文件路径)
        data_dict = df.to_dict(orient="records")
        return data_dict
    except Exception as e:
        print("读取xlsx文件出错：", e)
        return None


def 批量docx(docx模板路径, xlsx表格路径, 输出目录):
    # 示例：测试合并效果

    if not os.path.exists(docx模板路径):
        print("docx模板不存在")
        sys.exit()
    if not os.path.exists(xlsx表格路径):
        print("xlsx数据不存在")
        sys.exit()
    if not os.path.exists(输出目录):
        os.makedirs(输出目录)

    docx = 读docx(docx模板路径)
    xlsx = 读xlsx(xlsx表格路径)

    temp_copy_path = f'{时间_文件_分()}.docx'
    docx文件名名称 = os.path.split(docx模板路径)[1]

    try:
        doc = docx.save(temp_copy_path)
        for f6, f1 in enumerate(xlsx, 1):
            doc = Document(temp_copy_path)

            # 段落
            for f2 in doc.paragraphs:
                for f3 in f2.runs:
                    try:
                        f3.text = f3.text.format(**f1)
                    except KeyError as e:
                        print(f'表格缺少对象【{e}】')
                    except Exception as e:
                        print(f'未知报错：{e}')

            for f2 in doc.tables:
                for f3 in f2._cells:
                    for f4 in f3.paragraphs:
                        for f5 in f4.runs:
                            try:
                                f5.text = f5.text.format(**f1)
                            except KeyError as e:
                                print(f'表格缺少对象【{e}】')
                            except Exception as e:
                                print(f'未知报错：{e}')

            doc.save(f'{os.path.abspath(os.path.join(输出目录, docx文件名名称.format(**f1)))}')
            print(f"完成【{f6}/{len(xlsx)}】：{docx文件名名称.format(**f1)}")
    except Exception as e:
        print(f"出错：{e}")
        sys.exit()
    os.remove(temp_copy_path)


if __name__ == '__main__':
    pass
    # docx模板路径 = "g:\\全代码\\历史项目\\批量word报告\\1{ceshi}.docx"
    # xlsx表格路径 = "g:\\全代码\\历史项目\\批量word报告\\1.xlsx"
    # 输出目录='G:\\全代码\\历史项目\\批量word报告\\cs\\2026年3月13日'

    # 批量docx(docx模板路径, xlsx表格路径, 输出目录)
