"""
Table-related operations for Word Document Server.
"""
from docx.oxml.shared import OxmlElement, qn
from docx.oxml.ns import nsdecls
from docx.oxml import parse_xml


def set_cell_border(cell, **kwargs):
    """
    Set cell border properties.
    
    Args:
        cell: The cell to modify
        **kwargs: Border properties (top, bottom, left, right, val, color)
    """
    tc = cell._tc
    tcPr = tc.get_or_add_tcPr()
    
    # Create border elements
    for key, value in kwargs.items():
        if key in ['top', 'left', 'bottom', 'right']:
            tag = 'w:{}'.format(key)
            
            element = OxmlElement(tag)
            element.set(qn('w:val'), kwargs.get('val', 'single'))
            element.set(qn('w:sz'), kwargs.get('sz', '4'))
            element.set(qn('w:space'), kwargs.get('space', '0'))
            element.set(qn('w:color'), kwargs.get('color', 'auto'))
            
            tcBorders = tcPr.first_child_found_in("w:tcBorders")
            if tcBorders is None:
                tcBorders = OxmlElement('w:tcBorders')
                tcPr.append(tcBorders)
                
            tcBorders.append(element)


def apply_table_style(table, has_header_row=False, border_style=None, shading=None):
    """
    Apply formatting to a table.
    
    Args:
        table: The table to format
        has_header_row: If True, formats the first row as a header
        border_style: Style for borders ('none', 'single', 'double', 'thick')
        shading: 2D list of cell background colors (by row and column)
        
    Returns:
        True if successful, False otherwise
    """
    try:
        # Format header row if requested
        if has_header_row and table.rows:
            header_row = table.rows[0]
            for cell in header_row.cells:
                for paragraph in cell.paragraphs:
                    if paragraph.runs:
                        for run in paragraph.runs:
                            run.bold = True
        
        # Apply border style if specified
        if border_style:
            val_map = {
                'none': 'nil',
                'single': 'single',
                'double': 'double',
                'thick': 'thick'
            }
            val = val_map.get(border_style.lower(), 'single')
            
            # Apply to all cells
            for row in table.rows:
                for cell in row.cells:
                    set_cell_border(
                        cell,
                        top=True,
                        bottom=True,
                        left=True,
                        right=True,
                        val=val,
                        color="000000"
                    )
        
        # Apply cell shading if specified
        if shading:
            for i, row_colors in enumerate(shading):
                if i >= len(table.rows):
                    break
                for j, color in enumerate(row_colors):
                    if j >= len(table.rows[i].cells):
                        break
                    try:
                        # Apply shading to cell
                        cell = table.rows[i].cells[j]
                        shading_elm = parse_xml(f'<w:shd {nsdecls("w")} w:fill="{color}"/>')
                        cell._tc.get_or_add_tcPr().append(shading_elm)
                    except:
                        # Skip if color format is invalid
                        pass
        
        return True
    except Exception:
        return False



def copy_table(source_table, target_doc, ifadjustheight=True, height = 1):
    """
    Copy a table from one document to another.
    
    Args:
        source_table: The table to copy
        target_doc: The document to copy the table to
        
    Returns:
        The new table in the target document
    """ 
    # Create a new table with the same dimensions
    new_table = target_doc.add_table(rows=len(source_table.rows), cols=len(source_table.columns))
    
    # Try to apply the same style
    try:
        if source_table.style:
            new_table.style = 'Table Grid'
    except:
        # Fall back to default grid style
        try:
            new_table.style = 'Table Grid'
        except:
            pass
    from docx.enum.table import WD_TABLE_ALIGNMENT
    from docx.enum.table import WD_ALIGN_VERTICAL
    from docx.shared import Pt, Inches, Cm, RGBColor
    # Copy cell contents
    for i, row in enumerate(source_table.rows):
        for j, cell in enumerate(row.cells):
            for paragraph in cell.paragraphs:
                average_char_width_in_points = 6
                if paragraph.text:
                    new_table.cell(i,j).text = paragraph.text
                    new_table.cell(i,j).paragraphs[0].runs[0].font.name = "Times New Roman" #设置英文字体
                    new_table.cell(i,j).paragraphs[0].runs[0].font.size = Pt(10.5) # 字体大小
                    new_table.cell(i,j).paragraphs[0].runs[0]._element.rPr.rFonts.set(qn('w:eastAsia'), '仿宋') #设置中文字体
                    new_table.cell(i,j).paragraphs[0].paragraph_format.alignment = WD_TABLE_ALIGNMENT.CENTER
                    new_table.cell(i,j).vertical_alignment = WD_ALIGN_VERTICAL.CENTER
                    """
                    待添加：如何让表格自适应大小（autofit目前不知为何没有作用）
                    """
        if ifadjustheight:
            new_table.rows[i].height = Cm(height)
    try:
        new_table = merge_tables(new_table)
    except Exception as e:
        print(f"合并表格失败:{e}")
    from docx.shared import Inches

    return new_table


from collections import deque

def merge_tables(table):
    """BFS遍历，将相邻且相同单元格合并
    
    Args:
        table: 表格，docx库的Table类型
    Returns:
        合并后的表格
    """
    if not table or len(table.rows) == 0:
        return table
    
    rows = len(table.rows)
    cols = len(table.columns)
    
    # 创建访问标记矩阵
    visited = [[False for _ in range(cols)] for _ in range(rows)]
    
    # 定义四个方向的移动：上、右、下、左
    directions = [(0, 0), (0, 1), (1, 0), (0, 0)]
    
    for i in range(rows):
        for j in range(cols):
            if not visited[i][j]:
                current_cell = table.cell(i, j)
                current_text = current_cell.text.strip()
                
                if not current_text:  # 跳过空单元格
                    visited[i][j] = True
                    continue
                
                # BFS队列
                queue = deque()
                queue.append((i, j))
                visited[i][j] = True
                
                # 记录需要合并的单元格
                cells_to_merge = []
                
                while queue:
                    x, y = queue.popleft()
                    cells_to_merge.append((x, y))
                    
                    for dx, dy in directions:
                        nx, ny = x + dx, y + dy
                        
                        # 检查边界和访问状态
                        if 0 <= nx < rows and 0 <= ny < cols and not visited[nx][ny]:
                            neighbor_cell = table.cell(nx, ny)
                            neighbor_text = neighbor_cell.text.strip()
                            
                            if neighbor_text == current_text:
                                visited[nx][ny] = True
                                queue.append((nx, ny))
                
                # 如果有需要合并的单元格
                if len(cells_to_merge) > 1:
                    # 按行和列排序，确保左上角是第一个单元格
                    cells_to_merge.sort()
                    min_row, min_col = cells_to_merge[0]
                    max_row, max_col = cells_to_merge[-1]
                    
                    # 清空所有待合并单元格（包括换行符）
                    for x, y in cells_to_merge[1:]:
                        cell = table.cell(x, y)
                        # 删除所有段落（彻底清空）
                        for paragraph in list(cell.paragraphs):
                            p = paragraph._element
                            p.getparent().remove(p)
                        # 可选：添加一个空段落防止格式问题
                        cell.add_paragraph()
                    
                    # 执行合并
                    if max_row > min_row or max_col > min_col:
                        table.cell(min_row, min_col).merge(table.cell(max_row, max_col))

    return table

def fill_tables(Y_table_list, row, col, Y_Table_num, Y):
    """根据前端返回json块填写表格list，并实时跟进已填写表格数量
    目前只支持固定的缺陷图的填写
    
    Args:
        Y_table_list (list): 前端返回的json块
        row (int): 表格行数
        col (int): 表格列数
        Y_Table_num: json块中有几个表格
        Xu_Hao: 是第几个json块
        Y: 其他参数
        
    Return:
        Y1_TABLES: 三维，表和对应元素
        table_index_to_images: 字典，表索引到图片路径列表的映射
        Xu_Hao：到达第几个表了
    """
    table_index_to_images = {}
    Y_TABLES = [[["" for _ in range(row)] for _ in range(col)] for _ in range(Y_Table_num)]
    
    # 处理前端返回数据
    for l, table_dict in enumerate(Y_table_list):
        if table_dict:
            Y_TABLES[l][1][0] = Y
            Y_TABLES[l][1][1] = table_dict["QueXianLeiXing"]
            Y_TABLES[l][1][2] = table_dict["QueXianWeiZhi"]
            Y_TABLES[l][1][3] = table_dict["QueXianChiCun"]
            Y_TABLES[l][3][0] = table_dict["WeiZongDengJi"]
            Y_TABLES[l][3][1] = table_dict["visibility"]
            Y_TABLES[l][3][2] = table_dict["urgency"]
            Y_TABLES[l][3][3] = table_dict["repair_suggestion"]
        
        # 获取图片路径
        image_path = table_dict['Tupian_Dir']
        if image_path:
            # 确保路径是字符串形式
            if isinstance(image_path, list):
                table_index_to_images[l] = image_path.copy()
            else:
                table_index_to_images[l] = [str(image_path)]
    
    return Y_TABLES, table_index_to_images


