package org.dromara.inspection.service.impl;

import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import lombok.Data;
import org.apache.dubbo.config.annotation.DubboReference;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.mybatis.core.page.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.inspection.domain.OpsInspectionNode;
import org.dromara.inspection.domain.vo.*;
import org.dromara.inspection.mapper.OpsInspectionNodeMapper;
import org.dromara.personnel.domain.vo.OpsUserVo;
import org.dromara.personnel.service.impl.OpsUserServiceImpl;
import org.dromara.system.api.RemoteUserService;
import org.dromara.system.api.domain.vo.RemoteUserVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.dromara.inspection.domain.bo.OpsInspectionTestTaskBo;
import org.dromara.inspection.domain.OpsInspectionTestTask;
import org.dromara.inspection.mapper.OpsInspectionTestTaskMapper;
import org.dromara.inspection.service.IOpsInspectionTestTaskService;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.ZoneId;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * 运维-巡检-试验任务Service业务层处理
 *
 * @author LionLi
 * @date 2025-09-20
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class OpsInspectionTestTaskServiceImpl implements IOpsInspectionTestTaskService {

    private final OpsInspectionTestTaskMapper baseMapper;
    private final OpsInspectionNodeMapper nodeMapper;

    @Autowired
    private OpsInspectionTestPlanServiceImpl opsInspectionTestPlanService;
    @DubboReference
    private RemoteUserService userService;

    /**
     * 查询运维-巡检-试验任务
     *
     * @param id 主键
     * @return 运维-巡检-试验任务
     */
    @Override
    public OpsInspectionTestTaskVo queryById(Long id){
        OpsInspectionTestTaskVo opsInspectionTestTaskVo = baseMapper.selectVoById(id);
        List<OpsInspectionTestTaskVo> opsInspectionTestTaskVo1 = List.of(opsInspectionTestTaskVo);
        setValue(opsInspectionTestTaskVo1);
        return opsInspectionTestTaskVo1.getFirst();
    }

    /**
     * 分页查询运维-巡检-试验任务列表
     *
     * @param bo        查询条件
     * @param pageQuery 分页参数
     * @return 运维-巡检-试验任务分页列表
     */
    @Override
    public TableDataInfo<OpsInspectionTestTaskVo> queryPageList(OpsInspectionTestTaskBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<OpsInspectionTestTask> lqw = buildQueryWrapper(bo);
        Page<OpsInspectionTestTaskVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        setValue(result.getRecords());
        return TableDataInfo.build(result);
    }

    /**
     * 查询符合条件的运维-巡检-试验任务列表
     *
     * @param bo 查询条件
     * @return 运维-巡检-试验任务列表
     */
    @Override
    public List<OpsInspectionTestTaskVo> queryList(OpsInspectionTestTaskBo bo) {
        LambdaQueryWrapper<OpsInspectionTestTask> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<OpsInspectionTestTask> buildQueryWrapper(OpsInspectionTestTaskBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<OpsInspectionTestTask> lqw = Wrappers.lambdaQuery();
        lqw.orderByAsc(OpsInspectionTestTask::getId);
        lqw.eq(bo.getProjectId() != null, OpsInspectionTestTask::getProjectId, bo.getProjectId());
        lqw.like(StringUtils.isNotBlank(bo.getTaskName()), OpsInspectionTestTask::getTaskName, bo.getTaskName());
        lqw.eq(StringUtils.isNotBlank(bo.getTestObject()), OpsInspectionTestTask::getTestObject, bo.getTestObject());
        lqw.eq(bo.getBeginTime() != null, OpsInspectionTestTask::getBeginTime, bo.getBeginTime());
        lqw.eq(bo.getEndTime() != null, OpsInspectionTestTask::getEndTime, bo.getEndTime());
        lqw.eq(StringUtils.isNotBlank(bo.getTimeInfo()), OpsInspectionTestTask::getTimeInfo, bo.getTimeInfo());
        lqw.eq(bo.getPerson() != null, OpsInspectionTestTask::getPerson, bo.getPerson());
        lqw.eq(StringUtils.isNotBlank(bo.getStatus()), OpsInspectionTestTask::getStatus, bo.getStatus());
        lqw.eq(bo.getTestPlanId() != null, OpsInspectionTestTask::getTestPlanId, bo.getTestPlanId());
        lqw.eq(StringUtils.isNotBlank(bo.getTestSetting()), OpsInspectionTestTask::getTestSetting, bo.getTestSetting());
        lqw.eq(bo.getPlanBeginTime() != null, OpsInspectionTestTask::getPlanBeginTime, bo.getPlanBeginTime());
//        lqw.eq(bo.getProgress() != null, OpsInspectionTestTask::getProgress, bo.getProgress());
        lqw.eq(StringUtils.isNotBlank(bo.getFailReason()), OpsInspectionTestTask::getFailReason, bo.getFailReason());
        lqw.eq(bo.getFailTime() != null, OpsInspectionTestTask::getFailTime, bo.getFailTime());
        lqw.eq(bo.getFailPhase() != null, OpsInspectionTestTask::getFailPhase, bo.getFailPhase());
        lqw.eq(StringUtils.isNotBlank(bo.getFaileAnalyze()), OpsInspectionTestTask::getFaileAnalyze, bo.getFaileAnalyze());
        lqw.eq(StringUtils.isNotBlank(bo.getFaileTips()), OpsInspectionTestTask::getFaileTips, bo.getFaileTips());
        lqw.eq(bo.getTestLongTime() != null, OpsInspectionTestTask::getTestLongTime, bo.getTestLongTime());
        lqw.eq(StringUtils.isNotBlank(bo.getTestFinal()), OpsInspectionTestTask::getTestFinal, bo.getTestFinal());
        lqw.eq(StringUtils.isNotBlank(bo.getFinalInfo()), OpsInspectionTestTask::getFinalInfo, bo.getFinalInfo());
        lqw.eq(StringUtils.isNotBlank(bo.getPauseFor()), OpsInspectionTestTask::getPauseFor, bo.getPauseFor());
        lqw.eq(bo.getPauseTime() != null, OpsInspectionTestTask::getPauseTime, bo.getPauseTime());
        return lqw;
    }

    /**
     * 新增运维-巡检-试验任务
     *
     * @param bo 运维-巡检-试验任务
     * @return 是否新增成功
     */
    @Override
    public Boolean insertByBo(OpsInspectionTestTaskBo bo) {
        OpsInspectionTestTask add = MapstructUtils.convert(bo, OpsInspectionTestTask.class);
        validEntityBeforeSave(add);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setId(add.getId());
        }
        return flag;
    }

    /**
     * 修改运维-巡检-试验任务
     *
     * @param bo 运维-巡检-试验任务
     * @return 是否修改成功
     */
    @Override
    public R<Void> updateByBo(OpsInspectionTestTaskBo bo) {
        OpsInspectionTestTask update = MapstructUtils.convert(bo, OpsInspectionTestTask.class);
        validEntityBeforeSave(update);

        if(update == null){
            return R.fail();
        }

        OpsInspectionTestTaskVo oldVo = baseMapper.selectVoById(bo.getId());

        if (!oldVo.getStatus().equals("5") && bo.getStatus().equals("5")){
            //判断节点是否全部完成
            List<String> split = Arrays.stream(bo.getNodeIds().split(",")).toList();
            LambdaQueryWrapper<OpsInspectionNode> nodeLambdaQueryWrapper = new LambdaQueryWrapper<>();
            nodeLambdaQueryWrapper.in(OpsInspectionNode::getId, split);
            //全部节点
            List<OpsInspectionNodeVo> nodeVos = nodeMapper.selectVoList(nodeLambdaQueryWrapper);
            boolean isAllFinish = true;
            for (OpsInspectionNodeVo nodeVo : nodeVos) {
                if (nodeVo.getStatus().equals("2")) {
                    isAllFinish = false;
                    break;
                }
            }
            if (!isAllFinish){
                return R.fail("节点尚未全部完成");
            }
        }

        // 使用 UpdateWrapper 更新包括 null 的字段
        UpdateWrapper<OpsInspectionTestTask> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("id", bo.getId());

        // 手动设置需要更新的字段，包括可能为 null 的字段
        updateWrapper.set("task_name", update.getTaskName())
            .set("test_object", update.getTestObject())
            .set("begin_time", update.getBeginTime())
            .set("end_time", update.getEndTime())
            .set("time_info", update.getTimeInfo())
            .set("person", update.getPerson())
            .set("status", update.getStatus())
            .set("test_plan_id", update.getTestPlanId())
            .set("test_setting", update.getTestSetting())
            .set("plan_begin_time", update.getPlanBeginTime())
            .set("fail_reason", update.getFailReason())
            .set("fail_time", update.getFailTime())
            .set("fail_phase", update.getFailPhase())
            .set("faile_analyze", update.getFaileAnalyze())
            .set("faile_tips", update.getFaileTips())
            .set("test_long_time", update.getTestLongTime())
            .set("test_final", update.getTestFinal())
            .set("final_info", update.getFinalInfo())
            .set("pause_for", update.getPauseFor())
            .set("pause_time", update.getPauseTime());

        boolean b = baseMapper.update(updateWrapper) > 0;
        if (b){
            return R.ok();
        }else {
            return R.fail();
        }
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(OpsInspectionTestTask entity){
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 校验并批量删除运维-巡检-试验任务信息
     *
     * @param ids     待删除的主键集合
     * @param isValid 是否进行有效性校验
     * @return 是否删除成功
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if(isValid){
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return baseMapper.deleteByIds(ids) > 0;
    }

    /**
     * 处理回显信息
     */
    private void setValue(List<OpsInspectionTestTaskVo> list){

        LambdaQueryWrapper<OpsInspectionNode> nodeWrapper = new LambdaQueryWrapper<>();

        for (OpsInspectionTestTaskVo vo : list) {

            if(vo.getPerson()!= null){
                List<RemoteUserVo> remoteUserVos = userService.selectListByIds(List.of(vo.getPerson()));
                if (remoteUserVos != null && !remoteUserVos.isEmpty()){
                    vo.setPersonInfo(remoteUserVos.getFirst());
                }
            }

            if (vo.getTestPlanId() != null){
                OpsInspectionTestPlanVo opsInspectionTestPlanVo = opsInspectionTestPlanService.queryById(vo.getTestPlanId());
                if (opsInspectionTestPlanVo != null){
                    vo.setTestPlan(opsInspectionTestPlanVo);
                }
            }

            //处理节点回显列表
            if (vo.getNodeIds() != null && !vo.getNodeIds().isEmpty()){

                List<String> stringList = Arrays.stream(vo.getNodeIds().split(",")).toList();

                nodeWrapper.clear();
                nodeWrapper.in(OpsInspectionNode::getId, stringList);
                List<OpsInspectionNodeVo> nodeVoList = nodeMapper.selectVoList(nodeWrapper);

                //处理进度百分比 完成节点 / 总节点 * 100
                if (nodeVoList != null && !nodeVoList.isEmpty()){
                    //统计完成节点
                    int finishCount = nodeVoList.stream().filter(nodeVo -> nodeVo.getStatus().equals("1")).toList().size();
                    if (finishCount == nodeVoList.size()){
                        vo.setProgress(new BigDecimal("100"));
                    }else {
                        vo.setProgress(BigDecimal.valueOf(finishCount).divide(BigDecimal.valueOf(nodeVoList.size()), 2, RoundingMode.DOWN).multiply(BigDecimal.valueOf(100.00)));
                    }
                }

                //处理节点列表
                if (vo.getNodeIds() != null && !vo.getNodeIds().isEmpty()){

                    List<OpsInspectionNodeVo> nodeVos = new ArrayList<>();
                    for (String id : stringList) {
                        OpsInspectionNodeVo nodeVo = nodeMapper.selectVoById(id);
                        if (nodeVo != null) {
                            nodeVos.add(nodeVo);
                        }
                    }
                    vo.setNodes(nodeVos);
                }

            }

        }

    }


    /**
     * 统计记录
     */
    public R<Object> record(Long projectId){

        LocalDate firstDay = LocalDate.now().withDayOfMonth(1);
        LocalDate lastDay = firstDay.plusMonths(1).minusDays(1);
        Date startDate = Date.from(firstDay.atStartOfDay(ZoneId.systemDefault()).toInstant());
        Date endDate = Date.from(lastDay.atTime(23, 59, 59).atZone(ZoneId.systemDefault()).toInstant());

        LambdaQueryWrapper<OpsInspectionTestTask> lqw = new LambdaQueryWrapper<>();
        lqw.eq(OpsInspectionTestTask::getProjectId,projectId);

        OpsInspectionTestTaskBo opsInspectionTestTaskBo = new OpsInspectionTestTaskBo();
        opsInspectionTestTaskBo.setProjectId(projectId);

        List<OpsInspectionTestTaskVo> list = queryList(opsInspectionTestTaskBo);
        if (list==null || list.isEmpty()){
            return R.fail("没有数据");
        }
        //筛选出本月数据
        List<OpsInspectionTestTaskVo> benyueList = list.stream().filter(vo -> vo.getPlanBeginTime() != null && vo.getPlanFinishTime() != null && vo.getPlanBeginTime().after(startDate) && vo.getPlanFinishTime().before(endDate)).toList();

        OpsInspectionTestTaskRecord record = new OpsInspectionTestTaskRecord();

        //完成实验数
        Long finishCount = 0L;
        //待分析记录
        Long failCount = 0L;
        //总共完成时间
        long totalTestTime = 0L;

        for (OpsInspectionTestTaskVo vo : benyueList) {
            //只统计开始和结束都在本月内的
            if (vo.getStatus().equals("5")){
                finishCount++;
                totalTestTime += vo.getPlanFinishTime().getTime() - vo.getPlanBeginTime().getTime();
            }

            if (vo.getStatus().equals("3") && vo.getUnPack().equals("1")){
                failCount++;
            }
        }

        record.setFinishCount(String.valueOf(finishCount));
        record.setFailCount(String.valueOf(failCount));
        if (!list.isEmpty() && !benyueList.isEmpty()) {
            record.setPassValue(String.valueOf(BigDecimal.valueOf(finishCount).divide(BigDecimal.valueOf(benyueList.size()), 2, RoundingMode.HALF_UP).multiply(new BigDecimal("100"))));
        }else {
            record.setPassValue("0");
        }
        if(finishCount >0 ) {
            record.setAverageTestTime(BigDecimal.valueOf((double) TimeUnit.MILLISECONDS.toMinutes(totalTestTime) / finishCount).toString());
        }else {
            record.setAverageTestTime("0");
        }
        //统计上一月的数据finalStartDate finalEndDate
        Date finalStartDate = Date.from(LocalDate.now().minusMonths(1).withDayOfMonth(1).atStartOfDay(ZoneId.systemDefault()).toInstant());
        Date finalEndDate  = Date.from(LocalDate.now().minusMonths(1).withDayOfMonth(1).plusMonths(1).minusDays(1).atTime(23, 59, 59).atZone(ZoneId.systemDefault()).toInstant());

        //上月数据列表
        List<OpsInspectionTestTaskVo> lastMonth = list.stream().filter(testTaskVo -> testTaskVo.getCreateTime().before(finalEndDate) && testTaskVo.getCreateTime().after(finalStartDate))
            .toList();
        log.info("上月数据列表:{}",lastMonth);

        //上月完成数
        finishCount = 0L;
        //上月实验通过率
        BigDecimal passValue = BigDecimal.ZERO;
        //上月平均实验时长
        totalTestTime = 0L;

        for (OpsInspectionTestTaskVo vo : lastMonth) {
            if (vo.getStatus().equals("5")){
                finishCount++;
                totalTestTime += vo.getPlanFinishTime().getTime() - vo.getPlanBeginTime().getTime();
            }
        }
        log.info("上月完成数:{}",finishCount);
        log.info("上月总共时长:{}",totalTestTime);

        //完成数增长率
        BigDecimal wcszzl;
        if (BigDecimal.valueOf(finishCount).compareTo(BigDecimal.ZERO) > 0) {
            wcszzl = BigDecimal.valueOf(Double.parseDouble(record.getFinishCount())).divide(BigDecimal.valueOf(finishCount), 2, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100.00));
        }else {
            wcszzl = BigDecimal.ZERO;
        }
        record.setFinishCountAdd(wcszzl.toString());

        //上月通过率
        if(BigDecimal.valueOf(lastMonth.size()).compareTo(BigDecimal.ZERO) > 0) {
            passValue = BigDecimal.valueOf(Double.valueOf(finishCount)).divide(BigDecimal.valueOf(lastMonth.size()), 2, RoundingMode.HALF_UP).multiply(new BigDecimal("100"));
        }
        log.info("上月通过率:{}",passValue);
        //进行比较 得出通过增长率
        BigDecimal tgzzl;
        if(passValue.compareTo(BigDecimal.ZERO) > 0) {
            tgzzl  = BigDecimal.valueOf(Double.parseDouble(record.getPassValue())).divide(passValue, 2, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100.00));
        }else {
            tgzzl = BigDecimal.ZERO;
        }
        record.setPassValueAdd(tgzzl.toString());

        //上月平均实验时间
        BigDecimal sypjsj;
        if (finishCount > 0) {
            sypjsj = BigDecimal.valueOf((double) TimeUnit.MILLISECONDS.toMinutes(totalTestTime) / finishCount);
        }else {
            sypjsj = BigDecimal.ZERO;
        }
        log.info("上月平均实验分钟数:{}",sypjsj);
        log.info("本月平均实验分钟数:{}",record.getAverageTestTime());
        //平均时间增长率
        BigDecimal sysjzzl;
        if (BigDecimal.valueOf(Double.parseDouble(record.getAverageTestTime())).compareTo(BigDecimal.ZERO) > 0) {
            sysjzzl=sypjsj.divide(BigDecimal.valueOf(Double.parseDouble(record.getAverageTestTime())), 2, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100.00));
        }else {
            sysjzzl = BigDecimal.ZERO;
        }
        log.info("实验分钟数增长率:{}",sysjzzl);
        record.setAverageTestTimeAdd(sysjzzl.toString());

        return R.ok(record);
    }


}
