package com.microservices.pms.project.service.impl;

import com.alibaba.fastjson2.JSON;
import com.microservices.common.core.exception.ServiceException;
import com.microservices.common.core.utils.DateUtils;
import com.microservices.common.core.utils.PageUtils;
import com.microservices.common.core.web.page.GenericsTableDataInfo;
import com.microservices.common.security.utils.SecurityUtils;
import com.microservices.pms.common.service.IPmsCommonService;
import com.microservices.pms.enums.TestsheetStepStatus;
import com.microservices.pms.product.service.IPmsProductModuleService;
import com.microservices.pms.project.domain.PmsProjectTestcase;
import com.microservices.pms.project.domain.PmsProjectTestsheetCases;
import com.microservices.pms.project.domain.vo.*;
import com.microservices.pms.project.mapper.PmsProjectTestsheetCasesMapper;
import com.microservices.pms.project.mapper.PmsProjectTestsheetIssuesMapper;
import com.microservices.pms.project.service.IPmsProjectTestcaseService;
import com.microservices.pms.project.service.IPmsProjectTestsheetCasesService;
import com.microservices.pms.project.service.IPmsProjectTestsheetService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;


/**
 * 测试单执行用例Service业务层处理
 *
 * @author microservices
 * @date 2023-11-24
 */
@Service
public class PmsProjectTestsheetCasesServiceImpl implements IPmsProjectTestsheetCasesService {
    @Autowired
    private PmsProjectTestsheetCasesMapper pmsProjectTestsheetCasesMapper;

    @Autowired
    private IPmsCommonService pmsCommonService;

    @Autowired
    private IPmsProjectTestcaseService pmsProjectTestcaseService;

    @Autowired
    private IPmsProjectTestsheetService pmsProjectTestsheetService;

    @Autowired
    private IPmsProductModuleService pmsProductModuleService;

    @Autowired
    private PmsProjectTestsheetIssuesMapper pmsProjectTestsheetIssuesMapper;


    /**
     * 查询测试单执行用例
     *
     * @param id 测试单执行用例主键
     * @return 测试单执行用例
     */
    @Override
    public PmsProjectTestsheetCases selectPmsProjectTestsheetCasesById(Long id) {
        PmsProjectTestsheetCases pmsProjectTestsheetCases = pmsProjectTestsheetCasesMapper.selectPmsProjectTestsheetCasesById(id);
        if (pmsProjectTestsheetCases == null) {
            throw new ServiceException("该测试执行用例不存在(Id[%d])", id);
        }
        pmsProjectTestsheetService.selectPmsProjectTestsheetById(pmsProjectTestsheetCases.getProjectTestsheetId());
        return pmsProjectTestsheetCases;
    }


    @Override
    public PmsProjectTestsheetCaseVo selectPmsProjectTestsheetCasesVoById(Long id) {
        PmsProjectTestsheetCases testsheetCases = this.selectPmsProjectTestsheetCasesById(id);
        return this.toPmsProjectTestsheetCaseDataVo(pmsProjectTestcaseService.selectPmsProjectTestcaseById(testsheetCases.getProjectTestcaseId()), testsheetCases.getProjectTestsheetId(), Stream.of(testsheetCases).collect(Collectors.toList()), false);
    }


    /**
     * 查询测试单执行用例列表
     *
     * @param pmsProjectTestsheetCases 测试单执行用例
     * @return 测试单执行用例
     */
    @Override
    public List<PmsProjectTestsheetCases> selectPmsProjectTestsheetCasesList(PmsProjectTestsheetCases pmsProjectTestsheetCases) {
        pmsProjectTestsheetService.selectPmsProjectTestsheetById(pmsProjectTestsheetCases.getProjectTestsheetId());
        return pmsProjectTestsheetCasesMapper.selectPmsProjectTestsheetCasesList(pmsProjectTestsheetCases);
    }

    @Override
    public Integer selectPmsProjectTestsheetCasesCount(PmsProjectTestsheetCases pmsProjectTestsheetCases) {
        pmsProjectTestsheetService.selectPmsProjectTestsheetById(pmsProjectTestsheetCases.getProjectTestsheetId());
        return pmsProjectTestsheetCasesMapper.selectPmsProjectTestsheetCasesCount(pmsProjectTestsheetCases);
    }

    @Override
    public Integer selectPmsProjectTestcaseByRootModuleForTestsheetCount(Long projectTestsheetId) {
        pmsProjectTestsheetService.selectPmsProjectTestsheetById(projectTestsheetId);
        return pmsProjectTestsheetCasesMapper.selectPmsProjectTestcaseByRootModuleForTestsheetCount(projectTestsheetId);
    }

    /**
     * 查询测试单执行用例列表
     *
     * @param searchVo 测试单执行用例
     * @return 测试单执行用例
     */
    @Override
    public GenericsTableDataInfo<PmsProjectTestsheetCaseVo> selectPmsProjectTestsheetCasesList(PmsProjectTestsheetCaseSearchVo searchVo) {
        pmsProjectTestsheetService.selectPmsProjectTestsheetById(searchVo.getProjectTestsheetId());
        PageUtils.startPage();
        PmsProjectTestcase pmsProjectTestcase = new PmsProjectTestcase();
        BeanUtils.copyProperties(searchVo, pmsProjectTestcase);
        pmsProjectTestcase.getParams().put("projectTestsheetId", searchVo.getProjectTestsheetId());
        pmsProjectTestcase.getParams().put("testerId", searchVo.getTesterId());
        pmsProjectTestcase.getParams().put("testStatus", searchVo.getTestStatus());
        if (pmsProjectTestcase.getPmsModuleId() != null && pmsProjectTestcase.getPmsModuleId() != 0) {
            List<Long> moduleIdList = pmsProductModuleService.selectChildrenPmsProductModuleIdList(pmsProjectTestcase.getPmsModuleId());
            pmsProjectTestcase.setChildrenModuleIdList(moduleIdList);
        }
        // 增加时排除已增加到测试单的用例
        List<PmsProjectTestcase> pmsProjectTestcaseList = searchVo.getAdd() ? pmsProjectTestcaseService.selectPmsProjectTestcaseForSelectList(pmsProjectTestcase) : pmsProjectTestcaseService.selectPmsProjectTestcaseForTestsheetList(pmsProjectTestcase);

        // 根据分页结果查询测试单执行用例详情
        PmsProjectTestsheetCases pmsProjectTestsheetCases = new PmsProjectTestsheetCases();
        com.microservices.common.core.utils.bean.BeanUtils.copyProperties(searchVo, pmsProjectTestsheetCases);
//        pmsProjectTestsheetCases.getParams().put("projectTestsheetId", searchVo.getProjectTestsheetId());
        List<Long> testcaseIdList = Optional.ofNullable(pmsProjectTestcaseList).orElse(Collections.emptyList()).stream().map(PmsProjectTestcase::getId).collect(Collectors.toList());
        if (!testcaseIdList.isEmpty()) {
            pmsProjectTestsheetCases.setTestcaseIdList(testcaseIdList);
        }
        List<PmsProjectTestsheetCases> testsheetCasesList = pmsProjectTestsheetCasesMapper.selectPmsProjectTestsheetCasesList(pmsProjectTestsheetCases);
        // 构建vo
        return PageUtils.toPage(pmsProjectTestcaseList, item -> this.toPmsProjectTestsheetCaseDataVo(item, pmsProjectTestsheetCases.getProjectTestsheetId(), testsheetCasesList, searchVo.getAdd()));
    }

    private PmsProjectTestsheetCaseVo toPmsProjectTestsheetCaseDataVo(PmsProjectTestcase pmsProjectTestcase, Long pmsProjectTestsheetId, List<PmsProjectTestsheetCases> testsheetCasesList, Boolean add) {
        PmsProjectTestsheetCaseVo dataVo = new PmsProjectTestsheetCaseVo();
        // 构建用例对象
        dataVo.setTestcaseDataVo(pmsProjectTestcaseService.toPmsProjectTestcaseDetailVo(pmsProjectTestcase));
        if (add) {
            return dataVo;
        }
        dataVo.setProjectTestsheetId(pmsProjectTestsheetId);
        dataVo.setProjectTestcaseId(pmsProjectTestcase.getId());
        // 匹配测试单中是否有该用例，存在用例加载执行结果
        PmsProjectTestsheetCases testsheetCases = Optional.ofNullable(testsheetCasesList).orElse(Collections.emptyList()).stream()
                .filter(item -> item.getProjectTestcaseId().equals(pmsProjectTestcase.getId())).findFirst().orElse(null);
        if (testsheetCases != null) {
            BeanUtils.copyProperties(testsheetCases, dataVo);
            // 关联缺陷数量
            dataVo.setTestIssueCount(pmsProjectTestsheetIssuesMapper.selectCountByTestsheetCasesId(testsheetCases.getId()));
            // 设置用例执行人
            dataVo.setTesterUser(pmsCommonService.getSimpleSysUserByGitlinkUserId(testsheetCases.getTesterId()));
            // 设置测试步骤结果
            List<PmsProjectTestsheetCaseStepVo> stepVoList = testsheetCases.getStepStatus() == null ? Collections.emptyList() : JSON.parseArray(testsheetCases.getStepStatus(), PmsProjectTestsheetCaseStepVo.class);
            Optional.ofNullable(dataVo.getTestcaseDataVo().getTestcaseStepList()).orElse(Collections.emptyList()).forEach(step -> {
                PmsProjectTestsheetCaseStepVo stepResult = stepVoList.stream().filter(item -> item.getStepId() != null && item.getStepId().equals(step.getId())).findFirst().orElse(null);
                step.setExecResult(stepResult != null ? stepResult.getStepStatus() : TestsheetStepStatus.INIT.ordinal());
            });
        }
        return dataVo;
    }


    /**
     * 新增测试单执行用例
     *
     * @param addCaseVo 测试单执行用例
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int insertPmsProjectTestsheetCases(PmsProjectTestsheetCaseInputVo addCaseVo) {
        pmsProjectTestsheetService.selectPmsProjectTestsheetById(addCaseVo.getProjectTestsheetId());
        addCaseVo.getIdList().forEach(id -> {
            PmsProjectTestsheetCases pmsProjectTestsheetCases = new PmsProjectTestsheetCases();
            pmsProjectTestsheetCases.setProjectTestsheetId(addCaseVo.getProjectTestsheetId());
            pmsProjectTestsheetCases.setProjectTestcaseId(id);
            pmsProjectTestsheetCases.setTestStatus(Long.valueOf(TestsheetStepStatus.INIT.ordinal()));

            pmsProjectTestsheetCases.setCreateBy(SecurityUtils.getUsername());
            pmsProjectTestsheetCases.setCreateTime(DateUtils.getNowDate());
            pmsProjectTestsheetCasesMapper.insertPmsProjectTestsheetCases(pmsProjectTestsheetCases);
        });
        return 1;
    }

    /**
     * 修改测试单执行用例
     *
     * @param testsheetCaseExecVo 测试单执行用例
     * @return 结果
     */
    @Override
    public int updatePmsProjectTestsheetCases(PmsProjectTestsheetCaseExecVo testsheetCaseExecVo) {
        PmsProjectTestsheetCases pmsProjectTestsheetCases = this.selectPmsProjectTestsheetCasesById(testsheetCaseExecVo.getId());
        pmsProjectTestsheetCases.setTestStatus(testsheetCaseExecVo.getTestStatus());
        if (testsheetCaseExecVo.getTestcaseStepList() != null && !testsheetCaseExecVo.getTestcaseStepList().isEmpty()) {
            pmsProjectTestsheetCases.setStepStatus(JSON.toJSONString(Optional.ofNullable(testsheetCaseExecVo.getTestcaseStepList()).orElse(Collections.emptyList())));
        }
        pmsProjectTestsheetCases.setUpdateBy(SecurityUtils.getUsername());
        pmsProjectTestsheetCases.setUpdateTime(DateUtils.getNowDate());
        if (testsheetCaseExecVo.getTesterId() !=null){
            pmsCommonService.getSimpleSysUserByGitlinkUserId(testsheetCaseExecVo.getTesterId());
        }
        pmsProjectTestsheetCases.setTesterId(testsheetCaseExecVo.getTesterId());
        return pmsProjectTestsheetCasesMapper.updatePmsProjectTestsheetCases(pmsProjectTestsheetCases);
    }

    @Override
    public int updatePmsProjectTestsheetCasesUpdateById(Long id) {
        PmsProjectTestsheetCases pmsProjectTestsheetCases = this.selectPmsProjectTestsheetCasesById(id);
        pmsProjectTestsheetCases.setUpdateBy(SecurityUtils.getUsername());
        pmsProjectTestsheetCases.setUpdateTime(DateUtils.getNowDate());
        return pmsProjectTestsheetCasesMapper.updatePmsProjectTestsheetCases(pmsProjectTestsheetCases);
    }

    /**
     * 批量删除测试单执行用例
     *
     * @param ids 需要删除的测试单执行用例主键
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int deletePmsProjectTestsheetCasesByIds(Long[] ids) {
        pmsProjectTestsheetIssuesMapper.deleteByProjectTestsheetCasesIds(ids);
        return pmsProjectTestsheetCasesMapper.deletePmsProjectTestsheetCasesByIds(ids);
    }
}
