package com.njcn.device.pms.service.majornetwork.impl;

import cn.afterturn.easypoi.excel.entity.ExportParams;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.njcn.common.pojo.enums.common.DataStateEnum;
import com.njcn.common.pojo.exception.BusinessException;
import com.njcn.device.pms.enums.PmsDeviceResponseEnum;
import com.njcn.device.pms.mapper.majornetwork.PowerGenerationUserMapper;
import com.njcn.device.pms.pojo.excel.PowerGenerationUserExcel;
import com.njcn.device.pms.pojo.param.PowerDistributionareaParam;
import com.njcn.device.pms.pojo.param.PowerGenerationUserParam;
import com.njcn.device.pms.pojo.param.PowerUserParam;
import com.njcn.device.pms.pojo.po.GeneratrixWire;
import com.njcn.device.pms.pojo.po.PowerGenerationUser;
import com.njcn.device.pms.pojo.po.StatationStat;
import com.njcn.device.pms.pojo.vo.PowerGenerationUserVO;
import com.njcn.device.pms.service.majornetwork.IDistributionMonitorService;
import com.njcn.device.pms.service.majornetwork.IGeneratrixWireService;
import com.njcn.device.pms.service.majornetwork.IPowerGenerationUserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.njcn.device.pms.service.majornetwork.IStatationStatService;
import com.njcn.device.pms.utils.PubUtil;
import com.njcn.poi.excel.ExcelUtil;
import com.njcn.poi.excel.PullDown;
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.vo.PvTerminalTreeVO;
import com.njcn.web.factory.PageFactory;
import com.njcn.web.pojo.param.BaseParam;
import com.njcn.web.utils.RequestUtil;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;
import java.util.stream.Collectors;


/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author hongawen
 * @since 2022-10-14
 */
@Service
@RequiredArgsConstructor
public class PowerGenerationUserServiceImpl extends ServiceImpl<PowerGenerationUserMapper, PowerGenerationUser> implements IPowerGenerationUserService {

    private final DeptFeignClient deptFeignClient;
    private final DicDataFeignClient dicDataFeignClient;
    private final IDistributionMonitorService iDistributionMonitorService;
    private final IStatationStatService statationStatService;
    private final IGeneratrixWireService generatrixWireService;

    @Override
    public boolean addPowerGenerationUser(PowerGenerationUserParam powerGenerationUserParam) {
        LambdaQueryWrapper<PowerGenerationUser> che = new LambdaQueryWrapper<>();
        che.eq(PowerGenerationUser::getId,powerGenerationUserParam.getId());
        int powerClientCount = this.count(che);
        if(powerClientCount>0){
            throw new BusinessException(PmsDeviceResponseEnum.POWERGENERATIONUSER_SAME);
        }
        checkParam(powerGenerationUserParam,false);
        PowerGenerationUser powerGenerationUser = new PowerGenerationUser();
        BeanUtils.copyProperties(powerGenerationUserParam,powerGenerationUser);
        powerGenerationUser.setConnectionDate(LocalDate.parse(powerGenerationUserParam.getConnectionDate()));
        powerGenerationUser.setStatus(DataStateEnum.ENABLE.getCode());
        return this.save(powerGenerationUser);
    }

    @Override
    public boolean updatePowerGenerationUser(PowerGenerationUserParam powerGenerationUserParam) {
        PowerGenerationUser powerGenerationUser = this.getById(powerGenerationUserParam.getId());
        if(Objects.isNull(powerGenerationUser)){
            throw new BusinessException(PmsDeviceResponseEnum.POWER_GEN_NOT_FIND);
        }
        checkParam(powerGenerationUserParam,true);
        BeanUtils.copyProperties(powerGenerationUserParam,powerGenerationUser);
        powerGenerationUser.setConnectionDate(LocalDate.parse(powerGenerationUserParam.getConnectionDate()));
        return this.updateById(powerGenerationUser);
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public boolean delPowerGenerationUser(List<String> powerGenerationUserIds) {
        iDistributionMonitorService.removeByIds(powerGenerationUserIds);
        return this.removeByIds(powerGenerationUserIds);
    }

    @Override
    public PowerGenerationUser getPowerGenerationUserById(String powerGenerationUserId) {
        return this.getById(powerGenerationUserId);
    }

    @Override
    public List<PowerGenerationUserVO> getPowerGenerationUserList(PowerDistributionareaParam powerDistributionareaParam) {
        LambdaQueryWrapper<PowerGenerationUser> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        List<String> deptIds =new ArrayList<>();
        if(StrUtil.isNotBlank(powerDistributionareaParam.getOrgId())){
            deptIds = deptFeignClient.getDepSonSelfCodetByDeptId(powerDistributionareaParam.getOrgId()).getData();
        }
        return this.baseMapper.getPowerGenerationUserSelect(deptIds,powerDistributionareaParam.getId());
    }

    @Override
    public Page<PowerGenerationUser> getPowerGenerationUserPageList(BaseParam baseParam) {
        LambdaQueryWrapper<PowerGenerationUser> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(PowerGenerationUser::getStatus, DataStateEnum.ENABLE.getCode())
                .and(StrUtil.isNotBlank(baseParam.getSearchValue()),i->i  .like(StrUtil.isNotBlank(baseParam.getSearchValue()),PowerGenerationUser::getName,baseParam.getSearchValue())
                        .or(StrUtil.isNotBlank(baseParam.getSearchValue()))
                        .like(StrUtil.isNotBlank(baseParam.getSearchValue()),PowerGenerationUser::getOrgName,baseParam.getSearchValue()))
                .orderByDesc(PowerGenerationUser::getCreateTime);
        return this.page(new Page<>(PageFactory.getPageNum(baseParam),PageFactory.getPageSize(baseParam)),lambdaQueryWrapper);
    }

    @Override
    public List<PowerGenerationUser> getGenerateElectricityUserList(PowerUserParam powerUserParam) {
        LambdaQueryWrapper<PowerGenerationUser> queryWrapper = new LambdaQueryWrapper<>();
        if (StrUtil.isNotBlank(powerUserParam.getId())){
            queryWrapper.eq(PowerGenerationUser::getId,powerUserParam.getId());
        }
        return this.list(queryWrapper);
    }

    @Override
    public void export() {
        ExportParams exportParams = new ExportParams("发电用户台账数据模板（带*字段均是必填,请严格按照模板标准填入数据）", "发电用户台账数据信息");
        List<PullDown> pullDowns=new ArrayList<>();
        //电源类别
        List<DictData> powerCategory = dicDataFeignClient.getDicDataByTypeCode(DicDataTypeEnum.POWER_CATEGORY.getCode()).getData();
        //电站类型
        List<DictData> powerStationType = dicDataFeignClient.getDicDataByTypeCode(DicDataTypeEnum.POWER_STATION_TYPE.getCode()).getData();
        //发电方式
        List<DictData> powerGeneration = dicDataFeignClient.getDicDataByTypeCode(DicDataTypeEnum.POWER_GENERATION.getCode()).getData();
        //电压等级
        List<DictData> devVoltage = dicDataFeignClient.getDicDataByTypeCode(DicDataTypeEnum.DEV_VOLTAGE.getCode()).getData();
        //能源消纳方式
        List<DictData> connectionMode = dicDataFeignClient.getDicDataByTypeCode(DicDataTypeEnum.CONNECTION_MODE.getCode()).getData();
        //用电客户状态
        List<DictData> eccStat = dicDataFeignClient.getDicDataByTypeCode(DicDataTypeEnum.ECC_STAT.getCode()).getData();

        PullDown pullDown;
        pullDown=new PullDown();
        pullDown.setFirstCol(6);
        pullDown.setLastCol(6);
        pullDown.setStrings(powerCategory.stream().map(DictData::getName).collect(Collectors.toList()));
        pullDowns.add(pullDown);
        pullDown=new PullDown();
        pullDown.setFirstCol(7);
        pullDown.setLastCol(7);
        pullDown.setStrings(powerStationType.stream().map(DictData::getName).collect(Collectors.toList()));
        pullDowns.add(pullDown);
        pullDown=new PullDown();
        pullDown.setFirstCol(8);
        pullDown.setLastCol(8);
        pullDown.setStrings(powerGeneration.stream().map(DictData::getName).collect(Collectors.toList()));
        pullDowns.add(pullDown);
        pullDown=new PullDown();
        pullDown.setFirstCol(9);
        pullDown.setLastCol(9);
        pullDown.setStrings(devVoltage.stream().map(DictData::getName).collect(Collectors.toList()));
        pullDowns.add(pullDown);
        pullDown=new PullDown();
        pullDown.setFirstCol(12);
        pullDown.setLastCol(12);
        pullDown.setStrings(connectionMode.stream().map(DictData::getName).collect(Collectors.toList()));
        pullDowns.add(pullDown);
        pullDown=new PullDown();
        pullDown.setFirstCol(13);
        pullDown.setLastCol(13);
        pullDown.setStrings(eccStat.stream().map(DictData::getName).collect(Collectors.toList()));
        pullDowns.add(pullDown);
        pullDown=new PullDown();
        pullDown.setFirstCol(20);
        pullDown.setLastCol(20);
        pullDown.setStrings(Arrays.asList("是","否"));
        pullDowns.add(pullDown);
        ExcelUtil.exportExcelPullDown(exportParams,"发电用户台账数据信息.xlsx",pullDowns, PowerGenerationUserExcel.class, new ArrayList<>());



    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void importGenerationUserExcel(List<PowerGenerationUserExcel.ErrMsg> list, HttpServletResponse response) {
        List<PowerGenerationUser> info=new ArrayList<>();
        List<PowerGenerationUserExcel.ErrMsg> errInfo=new ArrayList<>();
        if(CollUtil.isNotEmpty(list)){
            PowerGenerationUser user;
            //获取部门信息
            List<PvTerminalTreeVO> depts = deptFeignClient.allDeptList().getData();
            //电源类别
            List<DictData> powerCategory = dicDataFeignClient.getDicDataByTypeCode(DicDataTypeEnum.POWER_CATEGORY.getCode()).getData();
            //电站类型
            List<DictData> powerStationType = dicDataFeignClient.getDicDataByTypeCode(DicDataTypeEnum.POWER_STATION_TYPE.getCode()).getData();
            //发电方式
            List<DictData> powerGeneration = dicDataFeignClient.getDicDataByTypeCode(DicDataTypeEnum.POWER_GENERATION.getCode()).getData();
            //电压等级
            List<DictData> devVoltage = dicDataFeignClient.getDicDataByTypeCode(DicDataTypeEnum.DEV_VOLTAGE.getCode()).getData();
            //能源消纳方式
            List<DictData> connectionMode = dicDataFeignClient.getDicDataByTypeCode(DicDataTypeEnum.CONNECTION_MODE.getCode()).getData();
            //用电客户状态
            List<DictData> eccStat = dicDataFeignClient.getDicDataByTypeCode(DicDataTypeEnum.ECC_STAT.getCode()).getData();
            for (PowerGenerationUserExcel.ErrMsg msg : list) {
                String objNull = PubUtil.isObjNull(msg);
                if(StrUtil.isNotBlank(objNull)){
                    msg.setErrMsg(objNull);
                    errInfo.add(msg);
                    continue;
                }
                user=new PowerGenerationUser();
                user.setId(msg.getId());
                user.setName(msg.getName());

                List<PvTerminalTreeVO> deptList = depts.stream().filter(x -> x.getCode().contains(msg.getOrgId())).collect(Collectors.toList());
                if(CollUtil.isEmpty(deptList)){
                    String org = PubUtil.subString(msg.getOrgName().replace("国网",""));
                    List<PvTerminalTreeVO> deptName = depts.stream().filter(x -> x.getName().contains(org)).collect(Collectors.toList());
                    if(CollUtil.isNotEmpty(deptName)){
                        user.setOrgName(deptName.get(0).getName());
                        user.setOrgId(deptName.get(0).getCode());
                    }else{
                        msg.setErrMsg("组织机构不存在");
                        errInfo.add(msg);
                        continue;
                    }
                }else{
                    user.setOrgName(deptList.get(0).getName());
                    user.setOrgId(deptList.get(0).getCode());
                }
                user.setOperationName(msg.getOperationName());
                user.setOperationId(msg.getOperationId());
                user.setPowerCategory(PubUtil.getDicById(msg.getPowerCategory(),powerCategory));
                user.setPowerStationType(PubUtil.getDicById(msg.getPowerStationType(),powerStationType));
                user.setPowerGenerationMode(PubUtil.getDicById(msg.getPowerGenerationMode(),powerGeneration));
                user.setVoltageLevel(PubUtil.getDicById(msg.getVoltageLevel(),devVoltage));
                user.setSourceCapacity(msg.getSourceCapacity());
                user.setConnectionMode(PubUtil.getDicById(msg.getConnectionMode(),connectionMode));
                user.setGcStat(PubUtil.getDicById(msg.getGcStat(),eccStat));
                user.setPowerStationId(msg.getPowerStationId());
                user.setLineId(msg.getLineId());
                user.setPlatformId(msg.getPlatformId());
                user.setUserTag("发电用户");
                user.setIsUpToGrid("是".equals(msg.getIsUpToGrid())?1:0);
                DateTime dateTime = DateUtil.parseDate(msg.getConnectionDate());
                ZoneId zoneId = ZoneId.systemDefault();
                LocalDateTime localDateTime = dateTime.toInstant().atZone(zoneId).toLocalDateTime();
                user.setConnectionDate(localDateTime.toLocalDate());
                user.setStatus(1);
                user.setCreateBy(RequestUtil.getUserIndex());
                user.setCreateTime(LocalDateTimeUtil.now());
                user.setUpdateBy(RequestUtil.getUserIndex());
                user.setUpdateTime(LocalDateTimeUtil.now());
                info.add(user);
            }
            if(CollUtil.isNotEmpty(info)){
                info = info.stream().collect(Collectors.collectingAndThen
                        (Collectors.toCollection(() ->
                                new TreeSet<>(Comparator.comparing(o -> o.getId()))), ArrayList::new));
                List<String> ids = info.stream().map(PowerGenerationUser::getId).distinct().collect(Collectors.toList());
                List<PowerGenerationUserExcel.ErrMsg> subInfo = list.stream().filter(x -> ids.contains(x.getId())).collect(Collectors.toList());
                addSub(subInfo,devVoltage);
                this.remove(new LambdaQueryWrapper<PowerGenerationUser>()
                        .in(PowerGenerationUser::getId, ids)
                );
                this.saveBatch(info, 1000);
            }
            if (CollUtil.isNotEmpty(errInfo)) {
                PubUtil.exportExcel(DateUtil.now() + "_发电用户台账错误信息.xlsx", errInfo,PowerGenerationUserExcel.ErrMsg.class, response);
            }
        }


    }



    private void  checkParam(PowerGenerationUserParam powerGenerationUserParam,Boolean updateFlag){

        LambdaQueryWrapper<PowerGenerationUser> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(PowerGenerationUser::getName,powerGenerationUserParam.getName());

        if(updateFlag){
            lambdaQueryWrapper.ne(PowerGenerationUser::getId,powerGenerationUserParam.getId());
        }else {
            lambdaQueryWrapper.or().eq(PowerGenerationUser::getId,powerGenerationUserParam.getId());
        }

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

    }

    //变电站和线路插入
    public void addSub(List<PowerGenerationUserExcel.ErrMsg> info, List<DictData> devVoltage) {
        List<StatationStat> stats=new ArrayList<>();
        StatationStat stat;
        List<GeneratrixWire> wires=new ArrayList<>();
        GeneratrixWire wire;
        List<StatationStat> oldStat = statationStatService.list();
        List<String> statIds = oldStat.stream().map(StatationStat::getPowerId).distinct().collect(Collectors.toList());
        List<GeneratrixWire> oldWire = generatrixWireService.list();
        List<String> wireIds = oldWire.stream().map(x-> x.getId()+"_"+x.getStationId()).distinct().collect(Collectors.toList());
        //变电站集合
        ArrayList<PowerGenerationUserExcel.ErrMsg> statList = info.stream().collect(Collectors.collectingAndThen
                (Collectors.toCollection(() ->
                        new TreeSet<>(Comparator.comparing(o -> o.getPowerStationId()))), ArrayList::new));
        for (PowerGenerationUserExcel.ErrMsg errMsg : statList) {
            if(!statIds.contains(errMsg.getPowerStationId())){
                stat=new StatationStat();
                stat.setPowerId(errMsg.getPowerStationId());
                stat.setPowerName(errMsg.getPowerStationName());
                stat.setOrgId(errMsg.getOrgId());
                stat.setOrgName(errMsg.getOrgName());
                stat.setShouldBeNum(100);
                stat.setVoltageLevel(PubUtil.getDicById(errMsg.getVoltageLevel(),devVoltage));
                stat.setStatus(1);
                stat.setCreateBy(RequestUtil.getUserIndex());
                stat.setCreateTime(LocalDateTimeUtil.now());
                stat.setUpdateBy(RequestUtil.getUserIndex());
                stat.setUpdateTime(LocalDateTimeUtil.now());
                stats.add(stat);
            }
        }
        //线路
        ArrayList<PowerGenerationUserExcel.ErrMsg> wireList = info.stream().collect(Collectors.collectingAndThen
                (Collectors.toCollection(() ->
                        new TreeSet<>(Comparator.comparing(o -> o.getLineId()+";"+o.getPowerStationId()))), ArrayList::new));
        for (PowerGenerationUserExcel.ErrMsg errMsg : wireList){
            if(!wireIds.contains(errMsg.getLineId()+"_"+errMsg.getPowerStationId())){
                wire=new GeneratrixWire();
                wire.setId(errMsg.getLineId());
                wire.setName(errMsg.getLineName());
                wire.setStationId(errMsg.getPowerStationId());
                wire.setStationName(errMsg.getPowerStationName());
                wire.setGeneratrixName(errMsg.getPowerStationName());
                wire.setScale(PubUtil.getDicById(errMsg.getVoltageLevel(),devVoltage));
                wire.setStatus(1);
                wire.setCreateBy(RequestUtil.getUserIndex());
                wire.setCreateTime(LocalDateTimeUtil.now());
                wire.setUpdateBy(RequestUtil.getUserIndex());
                wire.setUpdateTime(LocalDateTimeUtil.now());
                wires.add(wire);
            }
        }
        if(CollUtil.isNotEmpty(stats)){
            statationStatService.saveBatch(stats);
        }
        if(CollUtil.isNotEmpty(wires)){
            generatrixWireService.saveBatch(wires);
        }
    }
}
