# 内置模块导入
from pathlib import Path
# 导入框架相关
from django.db import transaction
from django.shortcuts import get_object_or_404
from ninja_extra import api_controller, ControllerBase, route
# 导入权限相关
from ninja_extra.permissions import IsAuthenticated
from ninja_jwt.authentication import JWTAuth
# 导入数据库模型
from apps.project.models import Project
from apps.dict.models import Dict
from docxtpl import InlineImage
# 导入文档处理相关
from docxtpl import DocxTemplate
# 导入自己工具
from utils.chapter_tools.csx_chapter import create_csx_chapter_dict
from utils.util import get_ident, get_case_ident, get_testType
from utils.chen_response import ChenResponse
from utils.path_utils import project_path
from apps.createDocument.extensions.parse_rich_text import RichParser

# @api_controller("/generateJL", tags=['生成测试记录系列'], auth=JWTAuth(), permissions=[IsAuthenticated])
@api_controller("/generateJL", tags=['生成测试记录系列'])
class GenerateControllerJL(ControllerBase):
    @route.get("/create/caserecord", url_name="create-caserecord")
    @transaction.atomic
    def create_caserecord(self, id: int):
        """生成测试记录表格"""
        project_path_str = project_path(id)
        project_obj = get_object_or_404(Project, id=id)
        # 测试用例记录模版位置
        record_template_path = Path.cwd() / 'media' / project_path_str / 'form_template/jl' / '测试用例记录.docx'
        # 打开模版文档
        doc = DocxTemplate(record_template_path)
        # 准备返回的测试类型数组的嵌套
        test_type_len = Dict.objects.get(code='testType').dictItem.count()  # 测试类型的个数
        type_number_list = [i for i in range(1, test_type_len + 1)]  # 测试类型编号对应的列表
        list_list = [[] for j in range(1, test_type_len + 1)]  # 每个测试类型组合为一个列表[[],[],[],[]]
        # 查询出第一轮次
        round_one = project_obj.pField.filter(key=0).first()
        # 测试项的章节号预置处理 - 根据轮次生成list和dict的二维数据
        demand_prefix = '6.2'
        testType_list, last_chapter_items = create_csx_chapter_dict(round_one)
        # 找出所有测试项
        testDemands = round_one.rtField.all()
        # 首先轮询所有测试需求
        for demand in testDemands:
            type_index = type_number_list.index(int(demand.testType))
            demand_ident = get_ident(demand)
            # ~~~组装测试项~~~
            demand_last_chapter = last_chapter_items[demand.testType].index(demand.key) + 1
            demand_chapter = ".".join([demand_prefix, str(testType_list.index(demand.testType) + 1),
                                       str(demand_last_chapter)])
            demand_dict = {
                'name': demand.name,
                'ident': demand_ident,
                'chapter': demand_chapter,
                'item': []
            }
            # ~~~这里组装测试项里面的测试用例~~~
            for case in demand.tcField.all():
                step_list = []
                index = 1
                for one in case.step.all():
                    # 这里需要对operation富文本处理
                    rich_parser = RichParser(one.operation)
                    desc_list = rich_parser.get_final_list(doc, img_size=68)
                    # 这里需要对result富文本处理
                    rich_parser2 = RichParser(one.result)
                    res_list = rich_parser2.get_final_list(doc, img_size=75)
                    # 组装用例里面的步骤dict
                    passed = '通过'
                    if one.passed == '2':
                        passed = '未通过'
                    elif one.passed == '3':
                        passed = '未执行'
                    step_dict = {
                        'index': index,
                        'operation': desc_list,
                        'expect': one.expect,
                        'result': res_list,
                        'passed': passed,
                    }
                    index += 1
                    step_list.append(step_dict)
                # 这里判断里面的单个步骤的执行情况，来输出一个整个用例的执行情况
                exe_noncount = 0
                execution_str = '已执行'
                for ste in step_list:
                    if ste.get('execution') == '3':
                        exe_noncount += 1
                if exe_noncount > 0 and exe_noncount != len(step_list):
                    execution_str = '部分执行'
                elif exe_noncount == len(step_list):
                    execution_str = '未执行'
                else:
                    execution_str = '已执行'
                # 查询所有的problem
                problem_list = []
                problem_prefix = "PT"
                proj_ident = project_obj.ident
                for problem in case.caseField.all():
                    problem_list.append("_".join([problem_prefix, proj_ident, problem.ident]))
                # 组装用例的dict
                rich_parser3 = RichParser(case.timing_diagram)
                timing_diagram = rich_parser3.get_final_list(doc, img_size=115, height=50)
                has_timing_diagram = False
                if len(timing_diagram) > 0:
                    if isinstance(timing_diagram[0], InlineImage):
                        has_timing_diagram = True
                case_dict = {
                    'name': case.name,
                    'ident': get_case_ident(demand_ident, case),
                    'summary': case.summarize,
                    'initialization': case.initialization,
                    'premise': case.premise,
                    'design_person': case.designPerson,
                    'test_person': case.testPerson,
                    'monitor_person': case.monitorPerson,
                    'step': step_list,
                    'execution': execution_str,
                    'time': str(case.exe_time) if case.exe_time is not None else str(case.update_datetime),
                    'problems': "、".join(problem_list),
                    # 2025年4月24日新增
                    'has_timing_diagram': has_timing_diagram,
                    'timing_diagram': timing_diagram,
                }
                demand_dict['item'].append(case_dict)

            list_list[type_index].append(demand_dict)
        # 定义渲染上下文
        context = {}
        output_list = []
        for (index, li) in enumerate(list_list):
            qs = Dict.objects.get(code="testType").dictItem.get(key=str(index + 1))  # type:ignore
            context_str = qs.title
            sort = qs.sort
            table = {
                "type": context_str,
                "item": li,
                "sort": sort
            }
            output_list.append(table)
        # 排序
        output_list = sorted(output_list, key=(lambda x: x["sort"]))
        context["data"] = output_list

        doc.render(context)
        try:
            doc.save(Path.cwd() / "media" / project_path_str / "output_dir/jl" / "测试用例记录.docx")
            return ChenResponse(status=200, code=200, message="文档生成成功！")
        except PermissionError as e:
            return ChenResponse(status=400, code=400, message="模版文件已打开，请关闭后再试，{0}".format(e))
