"""测试结果 Excel 导出（screen_module / sdr_movie / hdr_movie 统一实现）。"""
import datetime
import os
import traceback


EXCEL_EXPORT_CONFIG = {
    "screen_module": {
        "title": "屏模组性能测试数据报告",
        "type_label": "屏模组",
        "log_prefix": "屏模组",
        "curve_type": "gamma",
        "has_accuracy": False,
        "column_widths": {"A": 18, "B": 18, "C": 18, "D": 18, "E": 18,
                          "F": 15, "G": 15},
    },
    "sdr_movie": {
        "title": "SDR Movie 性能测试数据报告",
        "type_label": "SDR Movie",
        "log_prefix": "SDR Movie",
        "curve_type": "gamma",
        "has_accuracy": True,
        "column_widths": {c: 18 for c in "ABCDEFG"},
    },
    "hdr_movie": {
        "title": "HDR Movie 性能测试数据报告",
        "type_label": "HDR Movie",
        "log_prefix": "HDR Movie",
        "curve_type": "eotf",
        "has_accuracy": True,
        "column_widths": {c: 18 for c in "ABCDEFG"},
    },
}


# ==================== 样式 ====================
def _build_styles(Font, Alignment, PatternFill, Border, Side):
    thin = Side(style="thin")
    return {
        "title_font": Font(name="微软雅黑", size=16, bold=True, color="FFFFFF"),
        "title_fill": PatternFill(start_color="4472C4", end_color="4472C4",
                                  fill_type="solid"),
        "title_alignment": Alignment(horizontal="center", vertical="center"),
        "section_font": Font(name="微软雅黑", size=13, bold=True, color="FFFFFF"),
        "section_fill": PatternFill(start_color="5B9BD5", end_color="5B9BD5",
                                    fill_type="solid"),
        "section_alignment": Alignment(horizontal="center", vertical="center"),
        "header_font": Font(name="微软雅黑", size=10, bold=True, color="FFFFFF"),
        "header_fill": PatternFill(start_color="70AD47", end_color="70AD47",
                                   fill_type="solid"),
        "header_alignment": Alignment(horizontal="center", vertical="center",
                                      wrap_text=True),
        "data_font": Font(name="微软雅黑", size=10),
        "data_alignment": Alignment(horizontal="center", vertical="center"),
        "label_font": Font(name="微软雅黑", size=10, bold=True),
        "thin_border": Border(left=thin, right=thin, top=thin, bottom=thin),
    }


# ==================== 通用写入 ====================
def _write_title(ws, styles, title_text):
    ws.merge_cells("A1:G1")
    ws["A1"] = title_text
    ws["A1"].font = styles["title_font"]
    ws["A1"].fill = styles["title_fill"]
    ws["A1"].alignment = styles["title_alignment"]
    ws.row_dimensions[1].height = 35


def _write_basic_info(ws, styles, row, type_label):
    ws.merge_cells(f"A{row}:B{row}")
    ws[f"A{row}"] = "📋 测试基本信息"
    ws[f"A{row}"].font = styles["section_font"]
    ws[f"A{row}"].fill = styles["section_fill"]
    ws[f"A{row}"].alignment = styles["section_alignment"]
    ws.row_dimensions[row].height = 25
    row += 1

    info_items = [
        ("测试时间", datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")),
        ("测试类型", type_label),
    ]
    for label, value in info_items:
        ws[f"A{row}"] = label
        ws[f"B{row}"] = value
        ws[f"A{row}"].font = styles["label_font"]
        ws[f"B{row}"].font = styles["data_font"]
        ws[f"A{row}"].border = styles["thin_border"]
        ws[f"B{row}"].border = styles["thin_border"]
        row += 1
    return row


def _write_section_header(ws, styles, row, text, span="A{r}:G{r}"):
    ws.merge_cells(span.format(r=row))
    ws[f"A{row}"] = text
    ws[f"A{row}"].font = styles["section_font"]
    ws[f"A{row}"].fill = styles["section_fill"]
    ws[f"A{row}"].alignment = styles["section_alignment"]
    ws.row_dimensions[row].height = 25
    return row + 1


def _write_headers(ws, styles, row, headers):
    for col_idx, header in enumerate(headers, start=1):
        cell = ws.cell(row=row, column=col_idx)
        cell.value = header
        cell.font = styles["header_font"]
        cell.fill = styles["header_fill"]
        cell.alignment = styles["header_alignment"]
        cell.border = styles["thin_border"]
    return row + 1


def _apply_row_style(ws, row, cols, styles, label_cols=()):
    for col in cols:
        cell = ws[f"{col}{row}"]
        cell.font = (styles["label_font"] if col in label_cols
                     else styles["data_font"])
        cell.border = styles["thin_border"]


def _apply_data_row(ws, row, cols, styles):
    for col in cols:
        cell = ws[f"{col}{row}"]
        cell.font = styles["data_font"]
        cell.alignment = styles["data_alignment"]
        cell.border = styles["thin_border"]


# ==================== 分区：色域 ====================
def _section_gamut(ws, styles, row, results, log):
    rgb_data = results.get_intermediate_data("gamut", "rgb")
    gamut_final_result = None
    if "gamut" in results.test_items:
        gamut_final_result = results.test_items["gamut"].final_result

    if not (rgb_data and len(rgb_data) >= 3):
        return row

    row = _write_section_header(ws, styles, row, "🎨 色域测试数据")

    if gamut_final_result:
        xy_coverage = gamut_final_result.get("coverage", 0)
        uv_coverage = (
            gamut_final_result.get("uv_coverage", 0)
            or gamut_final_result.get("uv_space_coverage", 0)
            or gamut_final_result.get("coverage_uv", 0)
            or 0
        )

        ws[f"A{row}"] = "参考标准"
        ws[f"B{row}"] = gamut_final_result.get("reference", "DCI-P3")
        ws[f"A{row}"].font = styles["label_font"]
        ws[f"B{row}"].font = styles["data_font"]
        ws[f"A{row}"].border = styles["thin_border"]
        ws[f"B{row}"].border = styles["thin_border"]
        row += 1

        ws[f"A{row}"] = "XY 色域覆盖率"
        ws[f"B{row}"] = f"{xy_coverage:.2f}%"
        ws[f"C{row}"] = "UV 色域覆盖率"
        ws[f"D{row}"] = f"{uv_coverage:.2f}%"
        _apply_row_style(ws, row, ["A", "B", "C", "D"], styles,
                         label_cols=("A", "C"))
        row += 1

    row = _write_headers(
        ws, styles, row,
        ["点位", "x 坐标", "y 坐标", "亮度 (cd/m²)", "", "", ""],
    )

    rgb_labels = ["Red", "Green", "Blue"]
    for i, result in enumerate(rgb_data[:3]):
        x, y, lv = result[0], result[1], result[2]
        ws[f"A{row}"] = rgb_labels[i]
        ws[f"B{row}"] = x
        ws[f"C{row}"] = y
        ws[f"D{row}"] = lv
        ws[f"B{row}"].number_format = "0.0000"
        ws[f"C{row}"].number_format = "0.0000"
        ws[f"D{row}"].number_format = "0.00"
        _apply_data_row(ws, row, ["A", "B", "C", "D"], styles)
        row += 1

    log("  添加色域数据", level="info")
    return row + 1


# ==================== 分区：Gamma / EOTF ====================
def _section_curve(ws, styles, row, results, log, curve_type):
    if curve_type == "gamma":
        section_title = "📊 Gamma 曲线数据"
        label_prefix = "Gamma"
        data_key = "gamma"
        value_header = "Gamma 值"
    else:
        section_title = "📊 EOTF 曲线数据"
        label_prefix = "EOTF"
        data_key = "eotf"
        value_header = "EOTF 值"

    gray_data = results.get_intermediate_data("shared", "gray")
    if not gray_data:
        gray_data = results.get_intermediate_data(curve_type, "gray")

    curve_final_result = None
    if curve_type in results.test_items:
        curve_final_result = results.test_items[curve_type].final_result

    if not (gray_data and len(gray_data) > 0 and curve_final_result):
        return row

    value_list = curve_final_result.get(data_key, [])
    L_bar_list = curve_final_result.get("L_bar", [])

    row = _write_section_header(ws, styles, row, section_title)

    valid_values = [
        item[3]
        for item in value_list
        if isinstance(item, (list, tuple))
        and len(item) >= 4
        and 0.5 < item[3] < 5.0
    ]
    if valid_values:
        avg_v = sum(valid_values) / len(valid_values)
        ws[f"A{row}"] = f"平均 {label_prefix}"
        ws[f"B{row}"] = f"{avg_v:.3f}"
        ws[f"C{row}"] = f"最大 {label_prefix}"
        ws[f"D{row}"] = f"{max(valid_values):.3f}"
        ws[f"E{row}"] = f"最小 {label_prefix}"
        ws[f"F{row}"] = f"{min(valid_values):.3f}"
        _apply_row_style(ws, row, ["A", "B", "C", "D", "E", "F"], styles,
                         label_cols=("A", "C", "E"))
        row += 1

    row = _write_headers(
        ws, styles, row,
        ["灰阶 (%)", "x 坐标", "y 坐标", "实测亮度\n(cd/m²)",
         "归一化亮度\n(L_bar)", value_header, ""],
    )

    total_points = len(gray_data)
    for i in range(total_points - 1, -1, -1):
        gray_level = (100 - int(i * 100 / (total_points - 1))
                      if total_points > 1 else 0)
        x, y, lv = gray_data[i][0], gray_data[i][1], gray_data[i][2]
        L_bar_val = L_bar_list[i] if i < len(L_bar_list) else 0

        val = None
        if (i < len(value_list)
                and isinstance(value_list[i], (list, tuple))
                and len(value_list[i]) >= 4):
            val = value_list[i][3]

        ws[f"A{row}"] = gray_level
        ws[f"B{row}"] = x
        ws[f"C{row}"] = y
        ws[f"D{row}"] = lv
        ws[f"E{row}"] = L_bar_val

        if val is not None and 0.5 < val < 5.0:
            ws[f"F{row}"] = val
            ws[f"F{row}"].number_format = "0.000"
        else:
            ws[f"F{row}"] = "N/A"

        ws[f"A{row}"].number_format = "0"
        ws[f"B{row}"].number_format = "0.0000"
        ws[f"C{row}"].number_format = "0.0000"
        ws[f"D{row}"].number_format = "0.00"
        ws[f"E{row}"].number_format = "0.0000"
        _apply_data_row(ws, row, ["A", "B", "C", "D", "E", "F"], styles)
        row += 1

    log(f"  添加 {label_prefix} 数据", level="info")
    return row + 1


# ==================== 分区：色度一致性 ====================
def _section_cct(ws, styles, row, results, log):
    gray_data = results.get_intermediate_data("shared", "gray")
    if not gray_data:
        gray_data = results.get_intermediate_data("cct", "gray")
    if not (gray_data and len(gray_data) > 1):
        return row

    gray_data_no_black = gray_data[:-1]

    row = _write_section_header(ws, styles, row, "🌈 色度一致性数据")

    x_coords = [d[0] for d in gray_data_no_black]
    y_coords = [d[1] for d in gray_data_no_black]
    ws[f"A{row}"] = "x 坐标范围"
    ws[f"B{row}"] = f"{min(x_coords):.4f} ~ {max(x_coords):.4f}"
    ws[f"C{row}"] = "y 坐标范围"
    ws[f"D{row}"] = f"{min(y_coords):.4f} ~ {max(y_coords):.4f}"
    _apply_row_style(ws, row, ["A", "B", "C", "D"], styles,
                     label_cols=("A", "C"))
    row += 1

    row = _write_headers(
        ws, styles, row,
        ["灰阶 (%)", "x 坐标", "y 坐标", "亮度 (cd/m²)", "", "", ""],
    )

    total_points = len(gray_data)
    for i in range(len(gray_data_no_black) - 1, -1, -1):
        x, y, lv = (gray_data_no_black[i][0],
                    gray_data_no_black[i][1],
                    gray_data_no_black[i][2])
        gray_level = (100 - int(i * 100 / (total_points - 1))
                      if total_points > 1 else 0)
        ws[f"A{row}"] = gray_level
        ws[f"B{row}"] = x
        ws[f"C{row}"] = y
        ws[f"D{row}"] = lv
        ws[f"A{row}"].number_format = "0"
        ws[f"B{row}"].number_format = "0.0000"
        ws[f"C{row}"].number_format = "0.0000"
        ws[f"D{row}"].number_format = "0.00"
        _apply_data_row(ws, row, ["A", "B", "C", "D"], styles)
        row += 1

    log("  添加色度一致性数据", level="info")
    return row + 1


# ==================== 分区：对比度 ====================
def _section_contrast(ws, styles, row, results, log):
    contrast_final_result = None
    if "contrast" in results.test_items:
        contrast_final_result = results.test_items["contrast"].final_result
    if not contrast_final_result:
        return row

    row = _write_section_header(ws, styles, row, "⚫⚪ 对比度测试数据")

    max_lv = contrast_final_result.get("max_luminance", 0)
    min_lv = contrast_final_result.get("min_luminance", 0)
    contrast_ratio = contrast_final_result.get("contrast_ratio", 0)
    info_items = [
        ("最大亮度（白场）", f"{max_lv:.2f} cd/m²"),
        ("最小亮度（黑场）", f"{min_lv:.4f} cd/m²"),
        ("对比度", f"{contrast_ratio:.0f}:1"),
    ]
    for label, value in info_items:
        ws[f"A{row}"] = label
        ws[f"B{row}"] = value
        ws[f"A{row}"].font = styles["label_font"]
        ws[f"B{row}"].font = styles["data_font"]
        ws[f"A{row}"].border = styles["thin_border"]
        ws[f"B{row}"].border = styles["thin_border"]
        row += 1

    log("  添加对比度数据", level="info")
    return row + 1


# ==================== 分区：色准 ====================
def _section_accuracy(ws, styles, row, results, log):
    accuracy_final_result = None
    if "accuracy" in results.test_items:
        accuracy_final_result = results.test_items["accuracy"].final_result
    if not accuracy_final_result:
        return row

    row = _write_section_header(ws, styles, row, "🎯 色准测试数据")

    avg_delta_e = accuracy_final_result.get("avg_delta_e", 0)
    max_delta_e = accuracy_final_result.get("max_delta_e", 0)
    min_delta_e = accuracy_final_result.get("min_delta_e", 0)
    excellent_count = accuracy_final_result.get("excellent_count", 0)
    good_count = accuracy_final_result.get("good_count", 0)
    poor_count = accuracy_final_result.get("poor_count", 0)

    ws[f"A{row}"] = "平均 ΔE"
    ws[f"B{row}"] = f"{avg_delta_e:.2f}"
    ws[f"C{row}"] = "最大 ΔE"
    ws[f"D{row}"] = f"{max_delta_e:.2f}"
    ws[f"E{row}"] = "最小 ΔE"
    ws[f"F{row}"] = f"{min_delta_e:.2f}"
    _apply_row_style(ws, row, ["A", "B", "C", "D", "E", "F"], styles,
                     label_cols=("A", "C", "E"))
    row += 1

    ws[f"A{row}"] = "优秀 (ΔE<3)"
    ws[f"B{row}"] = f"{excellent_count} 个"
    ws[f"C{row}"] = "良好 (3≤ΔE<5)"
    ws[f"D{row}"] = f"{good_count} 个"
    ws[f"E{row}"] = "偏差 (ΔE≥5)"
    ws[f"F{row}"] = f"{poor_count} 个"
    _apply_row_style(ws, row, ["A", "B", "C", "D", "E", "F"], styles,
                     label_cols=("A", "C", "E"))
    row += 1

    color_patches = accuracy_final_result.get("color_patches", [])
    delta_e_values = accuracy_final_result.get("delta_e_values", [])
    color_measurements = accuracy_final_result.get("color_measurements", [])

    if color_patches and delta_e_values:
        row = _write_headers(
            ws, styles, row,
            ["序号", "颜色名称", "x 坐标", "y 坐标",
             "亮度 (cd/m²)", "ΔE 2000", "等级"],
        )
        for idx, (color_name, delta_e) in enumerate(
                zip(color_patches, delta_e_values), start=1):
            if delta_e < 3:
                grade = "优秀"
            elif delta_e < 5:
                grade = "良好"
            else:
                grade = "偏差"

            x_val, y_val, lv_val = "N/A", "N/A", "N/A"
            if color_measurements and idx - 1 < len(color_measurements):
                m = color_measurements[idx - 1]
                if len(m) >= 3:
                    x_val, y_val, lv_val = m[0], m[1], m[2]

            ws[f"A{row}"] = idx
            ws[f"B{row}"] = color_name
            ws[f"C{row}"] = x_val
            ws[f"D{row}"] = y_val
            ws[f"E{row}"] = lv_val
            ws[f"F{row}"] = delta_e
            ws[f"G{row}"] = grade

            ws[f"A{row}"].number_format = "0"
            if isinstance(x_val, (int, float)):
                ws[f"C{row}"].number_format = "0.0000"
            if isinstance(y_val, (int, float)):
                ws[f"D{row}"].number_format = "0.0000"
            if isinstance(lv_val, (int, float)):
                ws[f"E{row}"].number_format = "0.00"
            ws[f"F{row}"].number_format = "0.00"

            _apply_data_row(ws, row, ["A", "B", "C", "D", "E", "F", "G"], styles)
            row += 1

    log("  添加色准数据（含 xy 坐标和亮度）")
    return row + 1


# ==================== 主入口 ====================
def export_excel_report(result_dir, current_test_type, selected_items,
                        results, log):
    """根据测试类型生成统一格式的 Excel 报告。

    仅 current_test_type ∈ EXCEL_EXPORT_CONFIG 时应调用本函数；
    内部吞掉 ImportError（openpyxl 未装）与其他 Exception 并通过 log 记录。
    """
    if current_test_type not in EXCEL_EXPORT_CONFIG:
        return
    cfg = EXCEL_EXPORT_CONFIG[current_test_type]
    try:
        import openpyxl
        from openpyxl.styles import (
            Font, Alignment, PatternFill, Border, Side,
        )

        log("=" * 60)
        log(f"开始生成{cfg['log_prefix']} Excel 数据报告...")

        wb = openpyxl.Workbook()
        ws = wb.active
        ws.title = "测试数据"

        styles = _build_styles(Font, Alignment, PatternFill, Border, Side)

        _write_title(ws, styles, cfg["title"])
        row = _write_basic_info(ws, styles, 3, cfg["type_label"])
        row += 1  # 空行

        if "gamut" in selected_items:
            row = _section_gamut(ws, styles, row, results, log)
        if cfg["curve_type"] == "gamma" and "gamma" in selected_items:
            row = _section_curve(ws, styles, row, results, log, "gamma")
        if cfg["curve_type"] == "eotf" and "eotf" in selected_items:
            row = _section_curve(ws, styles, row, results, log, "eotf")
        if "cct" in selected_items:
            row = _section_cct(ws, styles, row, results, log)
        if "contrast" in selected_items:
            row = _section_contrast(ws, styles, row, results, log)
        if cfg["has_accuracy"] and "accuracy" in selected_items:
            row = _section_accuracy(ws, styles, row, results, log)

        for col, width in cfg["column_widths"].items():
            ws.column_dimensions[col].width = width

        timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
        excel_filename = f"测试数据_{timestamp}.xlsx"
        excel_path = os.path.join(result_dir, excel_filename)
        wb.save(excel_path)

        log(f"已保存: {excel_filename}", level="success")
        log("=" * 60, level="seperator")

    except ImportError:
        log("未安装 openpyxl 库，跳过 Excel 导出", level="error")
        log("   安装方法: pip install openpyxl")
    except Exception as e:
        log(f"Excel 导出失败: {str(e)}", level="error")
        log(traceback.format_exc())
