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.date.LocalDateTimeUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.dynamic.datasource.annotation.DS;
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.constant.OssPath;
import com.njcn.oss.utils.FileStorageUtil;
import com.njcn.process.enums.ProcessResponseEnum;
import com.njcn.process.mapper.SupvFileMapper;
import com.njcn.process.mapper.SupvPlanMapper;
import com.njcn.process.mapper.SupvPlanRelMapper;
import com.njcn.process.mapper.SupvProblemMapper;
import com.njcn.process.pojo.param.SupvPlanParam;
import com.njcn.process.pojo.po.*;
import com.njcn.process.pojo.vo.SupvPlanVO;
import com.njcn.process.service.ISupvFileService;
import com.njcn.process.service.ISupvPlanHisService;
import com.njcn.process.service.ISupvPlanService;
import com.njcn.system.api.DicDataFeignClient;
import com.njcn.system.enums.DicDataEnum;
import com.njcn.system.enums.DicDataTypeEnum;
import com.njcn.system.enums.SystemResponseEnum;
import com.njcn.system.pojo.po.DictData;
import com.njcn.user.api.DeptFeignClient;
import com.njcn.user.api.UserFeignClient;
import com.njcn.user.pojo.po.Dept;
import com.njcn.user.pojo.po.User;
import com.njcn.user.pojo.vo.PvTerminalTreeVO;
import com.njcn.web.factory.PageFactory;
import com.njcn.web.utils.RequestUtil;
import liquibase.pro.packaged.L;
import liquibase.pro.packaged.S;
import lombok.RequiredArgsConstructor;
import org.joda.time.DateTimeUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.sql.Timestamp;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author hongawen
 * @since 2023-06-21
 */
@Service
@RequiredArgsConstructor
public class SupvPlanServiceImpl extends ServiceImpl<SupvPlanMapper, SupvPlan> implements ISupvPlanService {

    private final DeptFeignClient deptFeignClient;

    private final DicDataFeignClient dicDataFeignClient;

    private final SupvFileMapper supvFileMapper;

    private final UserFeignClient userFeignClient;

    private final SupvProblemMapper supvProblemMapper;

    private final FileStorageUtil fileStorageUtil;
    private final ISupvPlanHisService supvPlanHisService;

    private final SupvPlanRelMapper supvPlanRelMapper;


    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean addPlan(SupvPlanParam supvPlanParam) {
        checkParam(supvPlanParam, false);
        SupvPlan supvPlan = new SupvPlan();
        BeanUtil.copyProperties(supvPlanParam, supvPlan);
        supvPlan.setPlanSupvDate(PubUtils.localDateFormat(supvPlanParam.getPlanSupvDate()));

        if(StrUtil.isNotBlank(supvPlanParam.getEffectEndTime())) {
            supvPlan.setEffectEndTime(PubUtils.localDateTimeFormat(supvPlanParam.getEffectEndTime()));
        }
        if(StrUtil.isNotBlank(supvPlanParam.getEffectStartTime())) {
            supvPlan.setEffectStartTime(PubUtils.localDateTimeFormat(supvPlanParam.getEffectStartTime()));
        }
        if(StrUtil.isNotBlank(supvPlanParam.getProblemOcTime())) {
            supvPlan.setProblemOcTime(PubUtils.localDateTimeFormat(supvPlanParam.getProblemOcTime()));
        }
        if(StrUtil.isNotBlank(supvPlanParam.getReportIssueTime())) {
            supvPlan.setReportIssueTime(PubUtils.localDateTimeFormat(supvPlanParam.getReportIssueTime()));
        }

        DictData dictData = dicDataFeignClient.getDicDataById(supvPlanParam.getSupvType()).getData();
        if(dictData.getCode().equals(DicDataEnum.Technical_Super.getCode())){
            if(StrUtil.isBlank(supvPlanParam.getSupvObjId())){
                throw new BusinessException("供电电压质量技术监督类型对象id不可为空！");
            }
        }else {
            supvPlan.setSupvObjId(IdUtil.simpleUUID());
        }

        if(!"01".equals(supvPlan.getEffectStatus())){
            if(Objects.isNull(supvPlan.getEffectStartTime()) ){
                throw new BusinessException("开始实施时间不可为空！");
            }
        }

        if("04".equals(supvPlan.getEffectStatus())){
            if(Objects.isNull(supvPlan.getEffectEndTime()) ){
                throw new BusinessException("结束实施时间不可为空！");
            }
        }

        supvPlan.setIsUploadHead(0);
        if(StrUtil.isNotBlank(supvPlan.getEffectUserId())){
            List<User> userList = userFeignClient.getUserByIdList(Stream.of(supvPlan.getEffectUserId()).collect(Collectors.toList())).getData();
            if(CollUtil.isNotEmpty(userList)){
                supvPlan.setEffectUserName(userList.get(0).getName());
            }
        }
        this.save(supvPlan);
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updatePlan(SupvPlanParam.UpdateSupvPlanParam supvPlanParam) {
        checkParam(supvPlanParam, true);
        SupvPlan byId = this.getById(supvPlanParam.getPlanId());

        SupvPlan supvPlan = new SupvPlan();
        BeanUtil.copyProperties(supvPlanParam, supvPlan);
        supvPlan.setPlanSupvDate(PubUtils.localDateFormat(supvPlanParam.getPlanSupvDate()));
        if(StrUtil.isNotBlank(supvPlanParam.getEffectEndTime())) {
            supvPlan.setEffectEndTime(PubUtils.localDateTimeFormat(supvPlanParam.getEffectEndTime()));
        }
        if(StrUtil.isNotBlank(supvPlanParam.getEffectStartTime())) {
            supvPlan.setEffectStartTime(PubUtils.localDateTimeFormat(supvPlanParam.getEffectStartTime()));
        }
        if(StrUtil.isNotBlank(supvPlanParam.getProblemOcTime())) {
            supvPlan.setProblemOcTime(PubUtils.localDateTimeFormat(supvPlanParam.getProblemOcTime()));
        }
        if(StrUtil.isNotBlank(supvPlanParam.getReportIssueTime())) {
            supvPlan.setReportIssueTime(PubUtils.localDateTimeFormat(supvPlanParam.getReportIssueTime()));
        }
        DictData dictData = dicDataFeignClient.getDicDataById(supvPlanParam.getSupvType()).getData();
        if(dictData.getCode().equals(DicDataEnum.Technical_Super.getCode())){
            if(StrUtil.isBlank(supvPlanParam.getSupvObjId())){
                throw new BusinessException("供电电压质量技术监督类型对象id不可为空！");
            }
        }

        if(StrUtil.isBlank(supvPlanParam.getSupvObjId()) || !byId.getSupvType().equals(supvPlanParam.getSupvType())){
            supvPlan.setSupvObjId(IdUtil.simpleUUID());
        }

        if(StrUtil.isNotBlank(supvPlan.getEffectUserId())){
            List<User> userList = userFeignClient.getUserByIdList(Stream.of(supvPlan.getEffectUserId()).collect(Collectors.toList())).getData();
            if(CollUtil.isNotEmpty(userList)){
                supvPlan.setEffectUserName(userList.get(0).getName());
            }
        }

        if(!"01".equals(supvPlan.getEffectStatus())){
            if(Objects.isNull(supvPlan.getEffectStartTime()) ){
                throw new BusinessException("开始实施时间不可为空！");
            }
        }

        if("04".equals(supvPlan.getEffectStatus())){
            if(Objects.isNull(supvPlan.getEffectEndTime()) ){
                throw new BusinessException("结束实施时间不可为空！");
            }
        }

        //实施问题
        List<SupvPlanHis> list =new ArrayList<>();
        if(1==byId.getIsUploadHead()){
            supvPlan.setIsUploadHead(3);

            SupvPlanHis planHis=new SupvPlanHis();
            planHis.setPlanId(supvPlan.getPlanId());
            planHis.setWorkPlanName(supvPlan.getWorkPlanName());
            planHis.setSupvOrgId(supvPlan.getSupvOrgId());
            Dept data = deptFeignClient.getDeptByCode(supvPlan.getSupvOrgId()).getData();
            if(ObjectUtil.isNull(data)){
                throw new BusinessException("监督单位不存在，请检查监督计划单位字段");
            }
            planHis.setSupvOrgName(data.getName());
            planHis.setPlanSupvDate(supvPlan.getPlanSupvDate());
            if (supvPlanParam instanceof SupvPlanParam.UpdateSupvPlanParam) {
                planHis.setOtherRemark(((SupvPlanParam.UpdateSupvPlanParam) supvPlanParam).getOtherRemarkHis());
                planHis.setApplyComment(((SupvPlanParam.UpdateSupvPlanParam) supvPlanParam).getApplyCommentHis());
            }
            planHis.setPlanStatus(supvPlanParam.getPlanStatus());
            planHis.setUpdateUserId(RequestUtil.getUserIndex());
            planHis.setUpdateUserName(RequestUtil.getUserNickname());
            planHis.setUpdateTime(LocalDateTime.now());
            planHis.setDeleteFlag("0");
            //判断是否已存在问题
             list = supvPlanHisService.list(new LambdaQueryWrapper<SupvPlanHis>()
                    .eq(SupvPlanHis::getPlanId, planHis.getPlanId())
                    .orderByDesc(SupvPlanHis::getUpdateTime)

            );
            if(CollUtil.isNotEmpty(list)){
                planHis.setParentId(list.get(0).getId());
            }
            planHis.setAdjustTime(LocalDateTime.now());
            planHis.setIsUploadHead(0);
            supvPlanHisService.save(planHis);
        }
        //报告出具时间
        if(StrUtil.isNotBlank(supvPlanParam.getReportIssueTime())){
            //查询是否存在实施问题
            if(CollUtil.isNotEmpty(list)){

            }
        }
       return this.updateById(supvPlan);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean delPlan(List<String> planIds) {
        LambdaQueryWrapper<SupvPlan> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.ne(SupvPlan::getIsUploadHead, 0).in(SupvPlan::getPlanId, planIds);
        int count = this.count(lambdaQueryWrapper);
        if (count > 0) {
            throw new BusinessException("请选择未上送国网的删除");
        }
        this.removeByIds(planIds);
        //删除问题

        LambdaQueryWrapper<SupvProblem> supvProblemLambdaQueryWrapper = new LambdaQueryWrapper<>();
        supvProblemLambdaQueryWrapper.in(SupvProblem::getPlanId, planIds);
        List<SupvProblem> supvProblemList = this.supvProblemMapper.selectList(supvProblemLambdaQueryWrapper);

        this.supvProblemMapper.delete(supvProblemLambdaQueryWrapper);

        List<String> busIds = supvProblemList.stream().map(SupvProblem::getProblemId).collect(Collectors.toList());
        if (CollUtil.isNotEmpty(busIds)) {
            LambdaQueryWrapper<SupvFile> fileLambdaQueryWrapper = new LambdaQueryWrapper<>();
            fileLambdaQueryWrapper.in(SupvFile::getBusiId, busIds);

            List<SupvFile> supvFiles = supvFileMapper.selectList(fileLambdaQueryWrapper);

            for(SupvFile supvFile: supvFiles){
                fileStorageUtil.deleteFile(supvFile.getFileUrl());
            }

            supvFileMapper.delete(fileLambdaQueryWrapper);
        }
        return true;
    }

    @Override
    public Page<SupvPlanVO> pagePlan(SupvPlanParam supvPlanParam) {
        LambdaQueryWrapper<SupvPlan> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        if (StrUtil.isNotBlank(supvPlanParam.getPlanOrgId())) {
            List<String> deptIds = deptFeignClient.getDepSonSelfCodetByCode(supvPlanParam.getPlanOrgId()).getData();
            lambdaQueryWrapper.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());
        }
        if(StrUtil.isNotBlank(supvPlanParam.getSortBy())){
            if(supvPlanParam.getOrderBy().equals("desc")){
                lambdaQueryWrapper.orderByDesc(SupvPlan::getPlanSupvDate);
            }else {
                lambdaQueryWrapper.orderByAsc(SupvPlan::getPlanSupvDate);

            }
        }else {
            lambdaQueryWrapper.orderByDesc(SupvPlan::getCreateTime);
        }


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


        Page<SupvPlan> page = this.page(new Page<>(PageFactory.getPageNum(supvPlanParam), PageFactory.getPageSize(supvPlanParam)), lambdaQueryWrapper);
        List<SupvPlanVO> supvPlanVOList = BeanUtil.copyToList(page.getRecords(), SupvPlanVO.class);
        List<String> userIds = supvPlanVOList.stream().map(SupvPlanVO::getPlanUserId).distinct().collect(Collectors.toList());
        supvPlanVOList.forEach(item -> {
            PvTerminalTreeVO pvTerminalTreeVO = null;

            item.setSupvOrgName(mapCode.get(item.getSupvOrgId()).getName());
            if (mapCode.containsKey(item.getPlanOrgId())) {
                pvTerminalTreeVO = mapCode.get(item.getPlanOrgId());
                item.setPlanOrgName(pvTerminalTreeVO.getName());
                int deptLevel = pvTerminalTreeVO.getPids().split(StrUtil.COMMA).length;
                if (deptLevel == 2) {
                    //省
                    item.setProvince(pvTerminalTreeVO.getName());
                } else if (deptLevel == 3) {
                    //市
                    item.setCity(pvTerminalTreeVO.getName());
                    if (mapList.containsKey(pvTerminalTreeVO.getPid())) {
                        PvTerminalTreeVO pvTerminalTreeOne = mapList.get(pvTerminalTreeVO.getPid());
                        item.setProvince(pvTerminalTreeOne.getName());
                    }
                } else if (deptLevel == 4) {
                    //县
                    if (mapList.containsKey(pvTerminalTreeVO.getPid())) {
                        item.setCounty(pvTerminalTreeVO.getName());
                        PvTerminalTreeVO pvTerminalTreeOne = mapList.get(pvTerminalTreeVO.getPid());
                        if (Objects.nonNull(pvTerminalTreeOne)) {
                            item.setCity(pvTerminalTreeOne.getName());
                            if (mapList.containsKey(pvTerminalTreeOne.getPid())) {
                                PvTerminalTreeVO pvTerminalTreeTwo = mapList.get(pvTerminalTreeOne.getPid());
                                if (Objects.nonNull(pvTerminalTreeTwo)) {
                                    item.setProvince(pvTerminalTreeTwo.getName());
                                }
                            }
                        }
                    }
                }
            }

            if (mapCode.containsKey(item.getPlanOrgId())) {
                item.setPlanOrgName(mapCode.get(item.getPlanOrgId()).getName());
            }

//            SupvFile supvFile = supvFileMapper.selectOne(new LambdaQueryWrapper<SupvFile>().eq(SupvFile::getBusiId, item.getPlanId()).eq(SupvFile::getType, 0));
//            if (Objects.nonNull(supvFile)) {
//                item.setAttachmentName(supvFile.getAttachmentName());
//            }

            List<User> userList = userFeignClient.getUserByIdList(userIds).getData();
            Map<String, User> map = userList.stream().collect(Collectors.toMap(User::getId, Function.identity()));

            if (map.containsKey(item.getPlanUserId())) {
                item.setPlanUserName(map.get(item.getPlanUserId()).getName());
            }


        });
        Page<SupvPlanVO> pageVo = new Page<>();
        pageVo.setTotal(page.getTotal());
        pageVo.setPages(page.getPages());
        pageVo.setSize(page.getSize());
        pageVo.setRecords(supvPlanVOList);
        return pageVo;
    }

    @Override
    public boolean saveOrUpdatePlanRel(SupvPlanRel supvPlanRel) {
        if(StrUtil.isBlank(supvPlanRel.getObjId())){
            supvPlanRel.setRelObjId(IdUtil.simpleUUID());
            supvPlanRel.setCreateTimes(new Timestamp(new Date().getTime()));
            supvPlanRel.setUpdateTimes(new Timestamp(new Date().getTime()));
            supvPlanRel.setIsDelete("0");
            supvPlanRelMapper.insert(supvPlanRel);
        }else {
            supvPlanRel.setUpdateTimes(new Timestamp(new Date().getTime()));
            supvPlanRelMapper.updateById(supvPlanRel);
        }
        return true;
    }

    @Override
    public boolean delPlanRel(List<String> planRelIds) {
        int res = supvPlanRelMapper.deleteBatchIds(planRelIds);
        return res == planRelIds.size();
    }

    @Override
    public List<SupvPlanRel> planList(SupvPlanRel supvPlanRel) {
        LambdaQueryWrapper<SupvPlanRel> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(SupvPlanRel::getPlanId,supvPlanRel.getPlanId()).orderByDesc(SupvPlanRel::getCreateTimes);
        return supvPlanRelMapper.selectList(lambdaQueryWrapper);
    }


    private void checkParam(SupvPlanParam supvPlanParam, Boolean updateFlag) {

        LambdaQueryWrapper<SupvPlan> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(SupvPlan::getWorkPlanName, supvPlanParam.getWorkPlanName());

        if (updateFlag) {
            if (supvPlanParam instanceof SupvPlanParam.UpdateSupvPlanParam) {
                //修改
                lambdaQueryWrapper.ne(SupvPlan::getPlanId, ((SupvPlanParam.UpdateSupvPlanParam) supvPlanParam).getPlanId());
            }
        }

        int count = this.count(lambdaQueryWrapper);
        if (count > 0) {
            throw new BusinessException(ProcessResponseEnum.SUPV_PLAN_REPEAT);
        }

        //判断监督对象类型
   /*     if (StrUtil.isNotBlank(supvPlanParam.getSupvObjType())) {
            DictData dictData = dicDataFeignClient.getDicDataById(supvPlanParam.getSupvType()).getData();
            if (dictData.getCode().equals(DicDataEnum.New_Energy.getCode())) {
                if (StrUtil.isBlank(supvPlanParam.getSupvObjType())) {
                    throw new BusinessException("监督对象类型不可为空");
                }
                if (StrUtil.isBlank(supvPlanParam.getObjType())) {
                    throw new BusinessException("监督对象属性名称不可为空");
                }
                if (Objects.isNull(supvPlanParam.getObjCapacity())) {
                    throw new BusinessException("监督对象协议容量不可为空");
                }
            } else if (!dictData.getCode().equals(DicDataEnum.Technical_Super.getCode())) {
                if (StrUtil.isBlank(supvPlanParam.getSupvObjName())) {
                    throw new BusinessException("监督对象名称不可为空");
                }
                if (StrUtil.isBlank(supvPlanParam.getObjVoltageLevel())) {
                    throw new BusinessException("监督对象电压等级不可为空");
                }

            } else if (!dictData.getCode().equals(DicDataEnum.POWER_QUALITY.getCode())) {
                if (Objects.isNull(supvPlanParam.getObjCapacity())) {
                    throw new BusinessException("监督对象协议容量不可为空");
                }
            }
        }*/
        //判断时间范围
        if(StrUtil.isAllNotBlank(supvPlanParam.getEffectStartTime(),supvPlanParam.getEffectEndTime())||
                StrUtil.isAllNotBlank(supvPlanParam.getEffectStartTime(),supvPlanParam.getReportIssueTime())
        ){
            String problemOcTime1 = supvPlanParam.getProblemOcTime();
            if(StrUtil.isNotBlank(problemOcTime1)){
                //实施开始时间
                DateTime effectStartTime = DateUtil.parse(supvPlanParam.getEffectStartTime(), "yyyy-MM-dd HH:mm:ss");
                //问题发现时间
                DateTime problemOcTime = DateUtil.parse(problemOcTime1, "yyyy-MM-dd HH:mm:ss");
                Boolean fly = false;
                if(StrUtil.isNotBlank(supvPlanParam.getEffectEndTime())){
                    //实施结束时间
                    DateTime effectEndTime = DateUtil.parse(supvPlanParam.getEffectEndTime(), "yyyy-MM-dd HH:mm:ss");
                    if (DateUtil.isIn(problemOcTime, effectStartTime, effectEndTime)) {
                        fly = true;
                    }
                }
                if(StrUtil.isNotBlank(supvPlanParam.getReportIssueTime())){
                    //报告出具时间
                    DateTime reportIssueTime = DateUtil.parse(supvPlanParam.getReportIssueTime(), "yyyy-MM-dd HH:mm:ss");
                    if (DateUtil.isIn(problemOcTime, effectStartTime, reportIssueTime)) {
                        fly = true;
                    }
                }
                if (!fly) {
                    throw new BusinessException("问题发现时时间，不在实施开始时间到（实施结束时间/报告出具时间）范围内");
                }
            }
        }
    }


}
