package com.njcn.process.service.impl;


import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.njcn.common.pojo.exception.BusinessException;
import com.njcn.common.utils.PubUtils;
import com.njcn.oss.utils.FileStorageUtil;
import com.njcn.poi.excel.ExcelUtil;
import com.njcn.process.mapper.SupvFileMapper;
import com.njcn.process.mapper.SupvPlanMapper;
import com.njcn.process.mapper.SupvProblemMapper;
import com.njcn.process.pojo.param.SupvPlanParam;
import com.njcn.process.pojo.param.SupvProblemParam;
import com.njcn.process.pojo.po.SupvFile;
import com.njcn.process.pojo.po.SupvPlan;
import com.njcn.process.pojo.po.SupvProblem;
import com.njcn.process.pojo.vo.SupvProblemVO;
import com.njcn.process.service.ISupvPlanService;
import com.njcn.process.service.ISupvProblemService;
import com.njcn.system.api.DicDataFeignClient;
import com.njcn.system.enums.DicDataTypeEnum;
import com.njcn.system.pojo.po.DictData;
import com.njcn.user.api.DeptFeignClient;
import com.njcn.user.pojo.po.Dept;
import com.njcn.user.pojo.vo.PvTerminalTreeVO;
import com.njcn.web.factory.PageFactory;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author hongawen
 * @since 2023-06-21
 */
@Service
@RequiredArgsConstructor
public class SupvProblemServiceImpl extends ServiceImpl<SupvProblemMapper, SupvProblem> implements ISupvProblemService {

    private final DicDataFeignClient dicDataFeignClient;

    private final DeptFeignClient deptFeignClient;

    private final SupvFileMapper supvFileMapper;

    private final FileStorageUtil fileStorageUtil;

    private final ISupvPlanService iSupvPlanService;
    private final SupvPlanMapper supvPlanMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean addProblem(SupvProblemParam supvProblemParam) {
        checkParam(supvProblemParam.getPlanId(), supvProblemParam.getDiscoveryTime());
        SupvProblem supvProblem = new SupvProblem();
        BeanUtil.copyProperties(supvProblemParam, supvProblem);
        supvProblem.setPlanRectificationTime(PubUtils.beginTimeToLocalDateTime(supvProblemParam.getPlanRectificationTime()));
        if (StrUtil.isNotBlank(supvProblemParam.getRectificationTime())) {
            supvProblem.setRectificationTime(PubUtils.beginTimeToLocalDateTime(supvProblemParam.getRectificationTime()));
        }
        supvProblem.setIsUploadHead(0);
        this.save(supvProblem);
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateProblem(SupvProblemParam supvProblemParam) {
        checkParam(supvProblemParam.getPlanId(), supvProblemParam.getDiscoveryTime());
        SupvProblem supvProblem = new SupvProblem();
        BeanUtil.copyProperties(supvProblemParam, supvProblem);
        supvProblem.setPlanRectificationTime(PubUtils.beginTimeToLocalDateTime(supvProblemParam.getPlanRectificationTime()));
        if (StrUtil.isNotBlank(supvProblemParam.getRectificationTime())) {
            supvProblem.setRectificationTime(PubUtils.beginTimeToLocalDateTime(supvProblemParam.getRectificationTime()));
        }
        SupvProblem byId = this.getById(supvProblem.getProblemId());
        if (1 == byId.getIsUploadHead()) {
            supvProblem.setIsUploadHead(3);
        }
        this.updateById(supvProblem);
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean delProblem(List<String> problemIds) {
        LambdaQueryWrapper<SupvProblem> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.ne(SupvProblem::getIsUploadHead, 0).in(SupvProblem::getProblemId, problemIds);
        int count = this.count(lambdaQueryWrapper);
        if (count > 0) {
            throw new BusinessException("请选择未上送国网的删除");
        }
        this.removeByIds(problemIds);
        if (CollUtil.isNotEmpty(problemIds)) {
            LambdaQueryWrapper<SupvFile> fileLambdaQueryWrapper = new LambdaQueryWrapper<>();
            fileLambdaQueryWrapper.in(SupvFile::getBusiId, problemIds);
            List<SupvFile> supvFileList = supvFileMapper.selectList(fileLambdaQueryWrapper);
            supvFileList.forEach(item -> fileStorageUtil.getFileStream(item.getFileUrl()));
            supvFileMapper.delete(fileLambdaQueryWrapper);
        }
        return true;
    }

    @Override
    public Page<SupvProblem> pageProblem(SupvProblemParam supvProblemParam) {
        DictData stamped_report = dicDataFeignClient.getDicDataByCode("Stamped_Report").getData();

        LambdaQueryWrapper<SupvProblem> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(SupvProblem::getPlanId, supvProblemParam.getPlanId());
        Page<SupvProblem> page = this.page(new Page<>(PageFactory.getPageNum(supvProblemParam), PageFactory.getPageSize(supvProblemParam)), lambdaQueryWrapper);

        List<PvTerminalTreeVO> deptList = deptFeignClient.allDeptList().getData();
        Map<String, PvTerminalTreeVO> mapCode = deptList.stream().collect(Collectors.toMap(PvTerminalTreeVO::getCode, Function.identity()));

        for (SupvProblem item : page.getRecords()) {
            if (mapCode.containsKey(item.getDutyOrgId())) {
                item.setDutyOrgName(mapCode.get(item.getDutyOrgId()).getName());
            }

            List<SupvFile> supvFileList = supvFileMapper.selectList(new LambdaQueryWrapper<SupvFile>().eq(SupvFile::getBusiId, item.getProblemId()).eq(SupvFile::getType, 1));
            if (CollUtil.isNotEmpty(supvFileList)) {
                for (SupvFile supvFile : supvFileList) {
                    if (supvFile.getAttachmentType().equals(stamped_report.getId())) {
                        item.setAttachmentName(supvFile.getAttachmentName());
                    } else {
                        item.setAttachmentNameTwo(supvFile.getAttachmentName());
                    }

                }
            }

        }
        return page;
    }

    @Override
    public void problemList(SupvPlanParam supvPlanParam) {
        List<SupvProblemVO> supvProblemVOS = new ArrayList<>();
        LambdaQueryWrapper<SupvPlan> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        List<String> deptIds = deptFeignClient.getDepSonSelfCodetByCode(supvPlanParam.getPlanOrgId()).getData();
        lambdaQueryWrapper.select(SupvPlan::getPlanId).in(SupvPlan::getPlanOrgId, deptIds)
                .between(SupvPlan::getPlanSupvDate, DateUtil.parse(supvPlanParam.getSearchBeginTime(), DatePattern.NORM_DATE_PATTERN), DateUtil.parse(supvPlanParam.getSearchEndTime(), DatePattern.NORM_DATE_PATTERN))
                .eq(StrUtil.isNotBlank(supvPlanParam.getSupvType()), SupvPlan::getSupvType, supvPlanParam.getSupvType());

        List<String> planIds = supvPlanMapper.selectList(lambdaQueryWrapper).stream().map(SupvPlan::getPlanId).collect(Collectors.toList());
        if (CollUtil.isNotEmpty(planIds)) {
            supvProblemVOS = this.baseMapper.listDerive(planIds);
            if(CollUtil.isNotEmpty(supvProblemVOS)) {

                //监测点状态
                List<DictData> monitorTypeList = dicDataFeignClient.getDicDataByTypeCode(DicDataTypeEnum.MONITOR_TYPE.getCode()).getData();
                Map<String, DictData> mapMonitorType = monitorTypeList.stream().collect(Collectors.toMap(DictData::getId, Function.identity()));
                //问题类型
                List<DictData> problemTypeList = dicDataFeignClient.getDicDataByTypeCode(DicDataTypeEnum.SUPV_PROBLEM_TYPE.getCode()).getData();
                Map<String, DictData> mapProblemType = problemTypeList.stream().collect(Collectors.toMap(DictData::getId, Function.identity()));

                //问题类型
                List<DictData> problemLevelList = dicDataFeignClient.getDicDataByTypeCode(DicDataTypeEnum.problem_level_type.getCode().trim()).getData();
                Map<String, DictData> mapProblemLeve = problemLevelList.stream().collect(Collectors.toMap(DictData::getValue, Function.identity()));

                for (SupvProblemVO supvProblem : supvProblemVOS) {
                    Dept dept = deptFeignClient.getDeptByCode(supvProblem.getDutyOrgId()).getData();
                    supvProblem.setDutyOrgName(dept.getName());

                    if (mapMonitorType.containsKey(supvProblem.getMonitorType())) {
                        supvProblem.setMonitorType(mapMonitorType.get(supvProblem.getMonitorType()).getName());
                    }
                    if (mapProblemType.containsKey(supvProblem.getProblemType())) {
                        supvProblem.setProblemType(mapProblemType.get(supvProblem.getProblemType()).getName());
                    }
                    if (mapProblemLeve.containsKey(supvProblem.getProblemLevel())) {
                        supvProblem.setProblemLevel(mapProblemLeve.get(supvProblem.getProblemLevel()).getName());
                    }
                }
            }
        }

        ExcelUtil.exportExcel("实施问题信息.xlsx", SupvProblemVO.class, supvProblemVOS);

    }

    //判断是否存在时间范围内
    public void checkParam(String id, String time) {
        if (StrUtil.isNotBlank(time)) {
            SupvPlan supvPlan = iSupvPlanService.getById(id);
            if (ObjectUtil.isNotNull(supvPlan)) {
                //判断时间范围
                if (ObjectUtil.isAllNotEmpty(supvPlan.getEffectStartTime(), supvPlan.getEffectEndTime()) ||
                        ObjectUtil.isAllNotEmpty(supvPlan.getEffectStartTime(), supvPlan.getReportIssueTime())
                ) {
                    //实施开始时间
                    DateTime effectStartTime = DateUtil.parse(DateUtil.formatLocalDateTime(supvPlan.getEffectStartTime()), "yyyy-MM-dd HH:mm:ss");
                    //问题发现时间
                    DateTime problemOcTime = DateUtil.parse(time, "yyyy-MM-dd HH:mm:ss");
                    Boolean fly = false;
                    if (ObjectUtil.isNotNull(supvPlan.getEffectEndTime())) {
                        //实施结束时间
                        DateTime effectEndTime = DateUtil.parse(DateUtil.formatLocalDateTime(supvPlan.getEffectEndTime()), "yyyy-MM-dd HH:mm:ss");
                        if (DateUtil.isIn(problemOcTime, effectStartTime, effectEndTime)) {
                            fly = true;
                        }
                    }
                    if (ObjectUtil.isNotNull(supvPlan.getReportIssueTime())) {
                        //报告出具时间
                        DateTime reportIssueTime = DateUtil.parse(DateUtil.formatLocalDateTime(supvPlan.getReportIssueTime()), "yyyy-MM-dd HH:mm:ss");
                        if (DateUtil.isIn(problemOcTime, effectStartTime, reportIssueTime)) {
                            fly = true;
                        }
                    }
                    if (!fly) {
                        throw new BusinessException("问题发现时时间，不在实施开始时间到（实施结束时间/报告出具时间）范围内");

                    }
                }
            }
        }

    }

}
