package org.dromara.inspection.service.impl;

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.OpsInspectionTaskProblem;
import org.dromara.inspection.domain.vo.*;
import org.dromara.inspection.mapper.OpsInspectionNodeMapper;
import org.dromara.inspection.mapper.OpsInspectionTaskProblemMapper;
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.OpsInspectionTaskBo;
import org.dromara.inspection.domain.OpsInspectionTask;
import org.dromara.inspection.mapper.OpsInspectionTaskMapper;
import org.dromara.inspection.service.IOpsInspectionTaskService;

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

/**
 * 运维-巡检计划-任务Service业务层处理
 *
 * @author LionLi
 * @date 2025-09-20
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class OpsInspectionTaskServiceImpl implements IOpsInspectionTaskService {

    private final OpsInspectionTaskMapper baseMapper;
    private final OpsInspectionNodeMapper nodeMapper;
    private final OpsInspectionTaskProblemMapper problemMapper;

    @Autowired
    private OpsInspectionPlanServiceImpl opsInspectionPlanService;
    @DubboReference
    private RemoteUserService userService;

    /**
     * 查询运维-巡检计划-任务
     *
     * @param id 主键
     * @return 运维-巡检计划-任务
     */
    @Override
    public OpsInspectionTaskVo queryById(Long id){
        OpsInspectionTaskVo opsInspectionTaskVo = baseMapper.selectVoById(id);
        List<OpsInspectionTaskVo> opsInspectionTaskVo1 = List.of(opsInspectionTaskVo);
        buildEcho(opsInspectionTaskVo1);
        return opsInspectionTaskVo1.getFirst();
    }

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

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

    private LambdaQueryWrapper<OpsInspectionTask> buildQueryWrapper(OpsInspectionTaskBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<OpsInspectionTask> lqw = Wrappers.lambdaQuery();
        lqw.eq(bo.getId() != null, OpsInspectionTask::getId, bo.getId());
        lqw.eq(bo.getPersonId()!= null, OpsInspectionTask::getPersonId, bo.getPersonId());
        lqw.orderByAsc(OpsInspectionTask::getId);
        lqw.like(StringUtils.isNotBlank(bo.getTaskName()), OpsInspectionTask::getTaskName, bo.getTaskName());
        lqw.like(StringUtils.isNotBlank(bo.getInspectionObject()), OpsInspectionTask::getInspectionObject, bo.getInspectionObject());
        lqw.eq(bo.getBeginTime() != null, OpsInspectionTask::getBeginTime, bo.getBeginTime());
        lqw.eq(bo.getEndTime() != null, OpsInspectionTask::getEndTime, bo.getEndTime());
        lqw.eq(StringUtils.isNotBlank(bo.getTimeInfo()), OpsInspectionTask::getTimeInfo, bo.getTimeInfo());
        lqw.eq(bo.getPlanId() != null, OpsInspectionTask::getPlanId, bo.getPlanId());
        lqw.eq(bo.getProjectId() != null, OpsInspectionTask::getProjectId, bo.getProjectId());
        lqw.eq(bo.getTaskType() != null, OpsInspectionTask::getTaskType, bo.getTaskType());
        return lqw;
    }

    /**
     * 新增运维-巡检计划-任务
     *
     * @param bo 运维-巡检计划-任务
     * @return 是否新增成功
     */
    @Override
    public Boolean insertByBo(OpsInspectionTaskBo bo) {
        OpsInspectionTask add = MapstructUtils.convert(bo, OpsInspectionTask.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(OpsInspectionTaskBo bo) {
        OpsInspectionTask update = MapstructUtils.convert(bo, OpsInspectionTask.class);
        validEntityBeforeSave(update);

        //过滤出更新为完成任务的情况
        OpsInspectionTaskVo oldVo = baseMapper.selectVoById(bo.getId());
        //如果原来不为完成状态而更新为完成状态
        if (!oldVo.getTaskType().equals("4") && bo.getTaskType().equals("4")){

            //判断节点是否全部完成
            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("节点尚未全部完成");
            }

            //判断问题是否全部解决
            LambdaQueryWrapper<OpsInspectionTaskProblem> problemLqw = new LambdaQueryWrapper<>();
            problemLqw.eq(OpsInspectionTaskProblem::getTaskId, bo.getId());
            List<OpsInspectionTaskProblemVo> problems = problemMapper.selectVoList(problemLqw);
            for (OpsInspectionTaskProblemVo problem : problems) {
                if (problem.getFinish().equals("2")){
                    isAllFinish = false;
                    break;
                }
            }
            if (!isAllFinish){
                return R.fail("纪录的问题尚未完全解决");
            }
        }

        boolean b = baseMapper.updateById(update) > 0;

        if (b){
            return R.ok();
        }else {

            return R.fail("更新失败");
        }
    }

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

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

        //删除任务时删除节点和节点问题
        List<Long> problemIds = new ArrayList<>();
        LambdaQueryWrapper<OpsInspectionTaskProblem> problemLambdaQueryWrapper = new LambdaQueryWrapper<>();

        for (Long id : ids) {
            //删除节点
            OpsInspectionTaskVo taskVo = baseMapper.selectVoById(id);
            if (taskVo!= null){
                if (taskVo.getNodeIds()!=null){
                    nodeMapper.deleteByIds(Arrays.stream(taskVo.getNodeIds().split(",")).toList());
                }
            }
            //删除问题
            problemLambdaQueryWrapper.clear();
            problemLambdaQueryWrapper.eq(OpsInspectionTaskProblem::getId, id);
            List<OpsInspectionTaskProblemVo> problemVos = problemMapper.selectVoList(problemLambdaQueryWrapper);
            if (problemVos!= null && !problemVos.isEmpty()){
                problemMapper.deleteByIds(problemVos);
            }
        }

        return baseMapper.deleteByIds(ids) > 0;
    }

    /**
     * 巡检记录统计 1月 2周 3日
     */
    public R<OpsInspectionRecordVo> record(String type,Long projectId){
        //从任务列表中统计
        OpsInspectionTaskBo opsInspectionTaskBo = new OpsInspectionTaskBo();
        opsInspectionTaskBo.setProjectId(projectId);
        List<OpsInspectionTaskVo> opsInspectionTaskVos = this.queryList(opsInspectionTaskBo);

        Long cpsyl = 0L;
        Long ncsyl = 0L;
        Long fwzt = 0L;
        Long xysj = 0L;
        Long sbyxzt = 0L;

        Date startDate;
        Date endDate;

        OpsInspectionRecordVo recordVo = new OpsInspectionRecordVo();
        switch ( type){
            //统计今天
            case "1" ->{
                // 设置时间范围：今天的00:00:00到23:59:59
                startDate = Date.from(LocalDateTime.of(LocalDate.now(), LocalTime.MIN).atZone(ZoneId.systemDefault()).toInstant());
                endDate = Date.from(LocalDateTime.of(LocalDate.now(), LocalTime.MAX).atZone(ZoneId.systemDefault()).toInstant());
            }

            //统计本周
            case "2" ->{
                LocalDate today = LocalDate.now();
                LocalDate start = today.minusDays(today.getDayOfWeek().getValue() - 1);
                LocalDate end = start.plusDays(6);
                startDate = Date.from(start.atStartOfDay(ZoneId.systemDefault()).toInstant());
                endDate = Date.from(end.atTime(23, 59, 59).atZone(ZoneId.systemDefault()).toInstant());
            }

            //统计本月
            case "3" ->{
                LocalDate firstDay = LocalDate.now().withDayOfMonth(1);
                LocalDate lastDay = firstDay.plusMonths(1).minusDays(1);
                startDate = Date.from(firstDay.atStartOfDay(ZoneId.systemDefault()).toInstant());
                endDate = Date.from(lastDay.atTime(23, 59, 59).atZone(ZoneId.systemDefault()).toInstant());
            }

            default -> {
                return R.fail("未知类型");
            }
        }

        //完成巡检数
        Date finalStartDate = startDate;
        Date finalEndDate = endDate;

        //仅统计在指定时间段内完成的巡检任务
        List<OpsInspectionTaskVo> finishList = opsInspectionTaskVos.stream()
            .filter(taskVo -> taskVo.getFinishTime() != null && taskVo.getStartTime() != null && taskVo.getFinishTime().before(finalEndDate) && taskVo.getStartTime().after(finalStartDate))
            .filter(vo -> vo.getCreateTime().after(finalStartDate) && vo.getCreateTime().before(finalEndDate))
            .toList();
        recordVo.setFinishInspectionCount((long) finishList.size());

        //发现问题数 通过createTime统计
        int problemCount = 0;
        LambdaQueryWrapper<OpsInspectionTaskProblem> problemLqw = new LambdaQueryWrapper<>();
        problemLqw.eq(OpsInspectionTaskProblem::getProjectId, projectId);
        problemLqw.ge(OpsInspectionTaskProblem::getCreateTime, finalStartDate);
        problemLqw.le(OpsInspectionTaskProblem::getCreateTime, finalEndDate);

        List<OpsInspectionTaskProblemVo> problemVos = problemMapper.selectVoList(problemLqw);
        if (problemVos != null && !problemVos.isEmpty()){
            problemCount = problemVos.size();
        }
        recordVo.setProblemCount((long) problemCount);

        //已解决数 获取列表以供通用  从本月发现列表里筛选出已解决
        List<OpsInspectionTaskProblemVo> finishProblems = new ArrayList<>();
        if (problemVos == null || problemVos.isEmpty()){
            recordVo.setSolvedProblemCount(0L);
        }else {
            //过滤出完成的
            finishProblems.addAll(problemVos.stream().filter(vo -> vo.getFinish().equals("1")).toList());
            recordVo.setSolvedProblemCount((long) finishProblems.size());
        }

        // 计算总共耗时(毫秒)
        long durationMillis = 0L;
        for (OpsInspectionTaskProblemVo vo : finishProblems) {
            durationMillis += vo.getFinishTime().getTime() - vo.getFindTime().getTime();
        }
        //平均处理分钟
        if (finishProblems.isEmpty()){
            recordVo.setAverageCompletionTime(0L);
        }else {
            recordVo.setAverageCompletionTime(TimeUnit.MILLISECONDS.toMinutes(durationMillis) / finishProblems.size());
        }

        //解决效率 = 已解决数 / 已发现数总共数量 * 100
        BigDecimal problemCountBigDecimal = BigDecimal.valueOf(recordVo.getProblemCount());
        BigDecimal solvedProblemCountBigDecimal = BigDecimal.valueOf(recordVo.getSolvedProblemCount());

        if (solvedProblemCountBigDecimal.compareTo(BigDecimal.ZERO) < 1 || problemCountBigDecimal.compareTo(BigDecimal.ZERO) < 1){
            recordVo.setJjxl(BigDecimal.valueOf(0));
        }else {
            BigDecimal bigDecimal = solvedProblemCountBigDecimal.divide(problemCountBigDecimal, 2, RoundingMode.HALF_UP).multiply(new BigDecimal("100")).setScale(0, RoundingMode.HALF_UP);
            recordVo.setJjxl(bigDecimal);
        }

        if (problemVos != null) {
            for (OpsInspectionTaskProblemVo vo : problemVos) {
                switch (vo.getType()){
                    case "1" -> cpsyl++;
                    case "2" -> ncsyl++;
                    case "3" -> fwzt++;
                    case "4" -> xysj++;
                    case "5" -> sbyxzt++;
                }
            }
        }
        recordVo.setCpsyl(cpsyl);
        recordVo.setNcsyl(ncsyl);
        recordVo.setFwzt(fwzt);
        recordVo.setXysj(xysj);
        recordVo.setSbyxzt(sbyxzt);

        //巡检完成率
        BigDecimal xjwcl;
        //统计指定时间段内创建的巡检任务数
        int byxjs = opsInspectionTaskVos.stream()
            .filter(vo -> !vo.getCreateTime().before(finalStartDate) && !vo.getCreateTime().after(finalEndDate))
            .toList()
            .size();
        //完成 / 巡检数 * 100
        if (byxjs > 0) {
            xjwcl = BigDecimal.valueOf(recordVo.getFinishInspectionCount()).divide(BigDecimal.valueOf(byxjs), 2, RoundingMode.HALF_UP).multiply(new BigDecimal("100"));
        }else {
            xjwcl = BigDecimal.valueOf(0);
        }
        recordVo.setXjwcl(xjwcl.toString());

        //问题解决率
        BigDecimal wtjjl;
        //解决数 / 问题数 * 100
        if (problemVos == null || problemVos.isEmpty()){
            wtjjl = BigDecimal.valueOf(0);
        }else {
            wtjjl = BigDecimal.valueOf(recordVo.getSolvedProblemCount()).divide(BigDecimal.valueOf(problemVos.size()), 2, RoundingMode.HALF_UP).multiply(new BigDecimal("100"));
        }
        recordVo.setJjxl(wtjjl);

        return R.ok(recordVo);
    }


    /**
     * 构造回显信息
     */
    private void buildEcho(List<OpsInspectionTaskVo> taskVos) {
        //TODO 回显信息
        taskVos.forEach(taskVo -> {
            LambdaQueryWrapper<OpsInspectionNode> nodeWrapper = new LambdaQueryWrapper<>();

            if (taskVo.getPlanId()!=null) {
                OpsInspectionPlanVo opsInspectionPlanVo = opsInspectionPlanService.queryById(taskVo.getPlanId());
                if (opsInspectionPlanVo != null) {
                    taskVo.setPlan(opsInspectionPlanVo);
                }
            }

            if (taskVo.getPersonId()!=null) {
                List<RemoteUserVo> remoteUserVos = userService.selectListByIds(List.of(taskVo.getPersonId()));
                if (remoteUserVos != null && !remoteUserVos.isEmpty()) {
                    taskVo.setPerson(remoteUserVos.getFirst());
                }
            }

            //处理进度和节点信息
            if (taskVo.getNodeIds() != null && !taskVo.getNodeIds().isEmpty()){

                List<String> stringList = Arrays.stream(taskVo.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()){
                        taskVo.setTaskProgress(new BigDecimal("100"));
                    }else {
                        taskVo.setTaskProgress(BigDecimal.valueOf(finishCount).divide(BigDecimal.valueOf(nodeVoList.size()), 2, RoundingMode.DOWN).multiply(BigDecimal.valueOf(100.00)));
                    }
                }

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

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

            }

            //处理问题列表
            LambdaQueryWrapper<OpsInspectionTaskProblem> problemWrapper = new LambdaQueryWrapper<>();
            problemWrapper.eq(OpsInspectionTaskProblem::getTaskId, taskVo.getId());
            List<OpsInspectionTaskProblemVo> problemVos = problemMapper.selectVoList(problemWrapper);
            taskVo.setProblems(problemVos);

        });
    }

}
