package com.tofly.watermeter.custom.service.meterBusiness.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.tofly.common.core.util.DateUtil;
import com.tofly.common.oauth.exception.ToflyDeniedException;
import com.tofly.common.oauth.util.SecurityUtils;
import com.tofly.pojo.message.Messagepush;
import com.tofly.pojo.message.Messagerecipient;
import com.tofly.watermeter.custom.entity.meterBusiness.dto.*;
import com.tofly.watermeter.custom.mapper.TimedTaskMapper;
import com.tofly.watermeter.custom.mapper.meterBusiness.WareHousingMapper;
import com.tofly.watermeter.custom.service.meterBusiness.WareHousingService;
import com.tofly.watermeter.custom.service.meterBusiness.export.ExportCommonCodeService;
import com.tofly.watermeter.entity.Bwrkdetail;
import com.tofly.watermeter.entity.Bwrksbdatail;
import com.tofly.watermeter.entity.Bwrktotal;
import com.tofly.watermeter.entity.Bwsjdatail;
import com.tofly.watermeter.service.BwrkdetailService;
import com.tofly.watermeter.service.BwrksbdatailService;
import com.tofly.watermeter.service.BwrktotalService;
import com.tofly.watermeter.service.BwsjdatailService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import javax.servlet.http.HttpServletResponse;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 水表入库改动
 *
 * @author 泡泡
 */
@Service
public class WareHousingServiceImpl implements WareHousingService {

    @Autowired
    private WareHousingMapper wareHousingMapper;
    @Autowired
    private BwrkdetailService bwrkdetailService;
    @Autowired
    private BwrktotalService bwrktotalService;
    @Autowired
    private BwrksbdatailService bwrksbdatailService;
    @Autowired
    private BwsjdatailService bwsjdatailService;
    @Autowired
    private TimedTaskMapper timedTaskMapper;
    @Autowired
    private ExportCommonCodeService exportCommonCodeService;

    private final static String BWRKSBDATAIL = "TF_YWPN_BWRKSBDATAIL_W";

    private final static String BWRKDETAIL = "TF_YWPN_BWRKDETAIL_W";

    private static final String MESSAGE_TABLE_NAME = "TF_YWPN_MESSAGEPUSH_W";

    private final static String BWSJDATAIL = "TF_YWPN_BWSJDATAIL_W";

    private final static Integer MAX_INSERT_NUMBER = 1000;

    /**
     * 第一层：统计各个厂家入库、库存总数
     *
     * @param response response
     * @param dto      条件
     * @return page
     */
    @Override
    public Page count(HttpServletResponse response, Page page, WareHousingDto dto) {
        if (dto.getExport() == 1) {
            //导出
            exportCommonCodeService.exportCode(response, "countExportService", wareHousingMapper.count(dto));
        }
        return wareHousingMapper.count(page, dto);
    }

    /**
     * 第二层：查询厂家下各个口径水表信息
     *
     * @param response response
     * @param page     page
     * @param dto      条件
     * @return page
     */
    @Override
    public Page countByVendor(HttpServletResponse response, Page page, WareHousingDto dto) {
        if (dto.getExport() == 1) {
            //导出
            exportCommonCodeService.exportCode(response, "countByVendorService", wareHousingMapper.countByVendor(dto));
        }
        return wareHousingMapper.countByVendor(page, dto);
    }

    /**
     * 水表入库
     *
     * @param dto 数据
     * @return boolean
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public String  wareHousing(WareHousingEntity dto) {
        if (StringUtils.isEmpty(dto)) {
            throw new ToflyDeniedException("传入数据为空");
        }
//        List<WareHousingEntityDto> wareLists = dto.getDto();
        List<WareHousingEntityDto> wareLists = new ArrayList<>(new HashSet<>(dto.getDto()));

        //查询库存所以水表编号
        List<String> allTableCode = wareHousingMapper.getAllTableCode();

        StringBuilder sb = new StringBuilder();

        Iterator<WareHousingEntityDto> iterator = wareLists.iterator();
        //移除对比具有重复的数据
        while (iterator.hasNext()) {
            String sbbh = iterator.next().getSbbh();
            if (allTableCode.contains(sbbh)) {
                sb.append(sbbh).append(",");
                iterator.remove();
            }
        }
        Long userId = SecurityUtils.getUserId();

        if (!wareLists.isEmpty()) {
            List<Bwrksbdatail> resultList = new ArrayList<>();

            Long maxId = bwrkdetailService.getMaxId(BWRKSBDATAIL);

            Bwrksbdatail tail;

            //水表口径编码信息
            Map<String, Long> caliberMap = wareHousingMapper.getCode(1)
                    .stream().collect(Collectors.toMap(CodeDto::getCname, CodeDto::getCcode));
            //水表厂家编码信息
            Map<String, Long> vendorMap = wareHousingMapper.getCode(2)
                    .stream().collect(Collectors.toMap(CodeDto::getCname, CodeDto::getCcode));
            //水表类型编码信息
            Map<String, Long> typeMap = wareHousingMapper.getCode(3)
                    .stream().collect(Collectors.toMap(CodeDto::getCname, CodeDto::getCcode));

//        StringBuilder sb = new StringBuilder();
            String date = DateUtil.getDateFormat(new Date(), "yyyyMMdd");
            String batch = date + "-" + System.currentTimeMillis();
            for (WareHousingEntityDto ware : wareLists) {
                tail = new Bwrksbdatail();

                if (!"X".equals(ware.getSbbh().substring(0, 1)) && !"C".equals(ware.getSbbh().substring(0, 1))) {
                    throw new ToflyDeniedException("异常水表编号:" + ware.getSbbh() + "请确认首位编码是否正确");
                }

                //将水表口径、厂家、类型由字符转为编码
                if (StringUtils.isEmpty(ware.getSbcj())) {
                    tail.setBwSbcj(null);
                } else {
                    tail.setBwSbcj(vendorMap.get(ware.getSbcj()));
                }
                if (StringUtils.isEmpty(ware.getSbkj())) {
                    tail.setBwSbkj(null);
                } else {
                    tail.setBwSbkj(caliberMap.get(ware.getSbkj()));
                }
                if (StringUtils.isEmpty(ware.getSblx())) {
                    tail.setBwSblx(null);
                } else {
                    tail.setBwSblx(typeMap.get(ware.getSblx()));
                }
                //设置水表入库详情的值
                tail.setId(maxId);
                tail.setBwLsbh(batch);
                tail.setCreateUser(userId);
                tail.setBwSbbh(ware.getSbbh());
                maxId++;
                resultList.add(tail);
            }
            //入库
            int size = resultList.size();
            if (size <= MAX_INSERT_NUMBER) {
                wareHousingMapper.bulkStorage(resultList);
            } else {
                List<Bwrksbdatail> list;
                int number = (int) Math.ceil((float) size / MAX_INSERT_NUMBER);
                //截取下标范围
                int startIndex;
                int endIndex;

                for (int i = 1; i <= number; i++) {
                    startIndex = (i - 1) * MAX_INSERT_NUMBER;
                    if (i == number) {
                        endIndex = size;
                    } else {
                        endIndex = i * MAX_INSERT_NUMBER;
                    }
                    list = resultList.subList(startIndex, endIndex);
                    wareHousingMapper.bulkStorage(list);
                }
            }
            //添加批次
        /*Map<Long, List<Bwrksbdatail>> groupByCal = resultList.stream()
                .collect(Collectors.groupingBy(Bwrksbdatail::getBwSbkj));*/

            Map<String, List<Bwrksbdatail>> groupMap = resultList.stream()
                    .collect(Collectors.groupingBy(b -> b.getBwSbcj() + "," + b.getBwSbkj() + "," + b.getBwSblx()));

            //收集口径
//        List<Long> calCodeList = resultList.stream().map(Bwrksbdatail::getBwSbcj).collect(Collectors.toList());

            Set<String> splitCode = resultList.stream().map(b -> b.getBwSbcj() + "," + b.getBwSbkj() + "," + b.getBwSblx()).collect(Collectors.toSet());

            //流水编号
            String detailNumber = date + "-" + System.currentTimeMillis();

            Bwrkdetail bd;

            Long maxId1 = bwrkdetailService.getMaxId(BWRKDETAIL);

            List<Bwrkdetail> rkdetailList = new ArrayList<>();

            for (String code : splitCode) {
                if (groupMap.containsKey(code)) {
                    List<Bwrksbdatail> bwrksbdatails = groupMap.get(code);

                    String[] split = code.split(",");

                    bd = new Bwrkdetail();
                    bd.setId(maxId1);
                    bd.setBwSl((long) bwrksbdatails.size());
                    bd.setBwLsbh(detailNumber);
                    bd.setCreateUser(userId);

                    bd.setBwSbcj(split[0] != null ? Long.valueOf(split[0]) : null);
                    bd.setBwSbkj(split[1] != null ? Long.valueOf(split[1]) : null);
                    bd.setBwSblx(split[2] != null ? Long.valueOf(split[2]) : null);

                    List<Long> idsList = bwrksbdatails.stream().map(Bwrksbdatail::getId).collect(Collectors.toList());

                    rkdetailList.add(bd);

                    bwrkdetailService.save(bd);

                    int idSize = idsList.size();
                    if (idSize <= MAX_INSERT_NUMBER) {
                        bwrksbdatailService.update(Wrappers.<Bwrksbdatail>lambdaUpdate()
                                .in(Bwrksbdatail::getId, idsList)
                                .set(Bwrksbdatail::getBwBz, bd.getId()));
                    } else {

                        List<Long> idList;
                        int number = (int) Math.ceil((float) idSize / MAX_INSERT_NUMBER);
                        //截取下标范围
                        int startIndex;
                        int endIndex;
                        for (int i = 1; i <= number; i++) {
                            startIndex = (i - 1) * MAX_INSERT_NUMBER;
                            if (i == number) {
                                endIndex = idSize;
                            } else {
                                endIndex = i * MAX_INSERT_NUMBER;
                            }
                            idList = idsList.subList(startIndex, endIndex);
                            bwrksbdatailService.update(Wrappers.<Bwrksbdatail>lambdaUpdate()
                                    .in(Bwrksbdatail::getId, idList)
                                    .set(Bwrksbdatail::getBwBz, bd.getId()));
                        }
                    }

                    maxId1++;
                }
            }

            //wareHousingMapper.insertBatch(rkdetailList);

            //库存更新
            //查询库存总数
            List<TableInfoDto> tableInfoDtos = wareHousingMapper.countInventory();

            if (tableInfoDtos.size() >= 1) {
                Bwrktotal total;
                for (TableInfoDto infoDto : tableInfoDtos) {
                    Bwrktotal bwrktotal = bwrktotalService.getOne(Wrappers.<Bwrktotal>lambdaQuery()
                            .eq(Bwrktotal::getBwSbcj, infoDto.getCj())
                            .eq(Bwrktotal::getBwSblx, infoDto.getLx())
                            .eq(Bwrktotal::getBwSbkj, infoDto.getKj()));

                    if (bwrktotal != null) {
                        bwrktotalService.update(Wrappers.<Bwrktotal>lambdaUpdate()
                                .set(Bwrktotal::getBwKczs, infoDto.getNum())
                                .set(Bwrktotal::getBwKcsl, infoDto.getNum() - bwrktotal.getBwSysl())
                                .eq(Bwrktotal::getId, bwrktotal.getId()));
                    } else {
                        total = new Bwrktotal();
                        total.setBwSbcj(infoDto.getCj());
                        total.setBwSbkj(infoDto.getKj());
                        total.setBwSblx(infoDto.getLx());
                        total.setBwKczs(infoDto.getNum());
                        total.setBwSysl(0L);
                        total.setBwKcsl(infoDto.getNum());

                        bwrktotalService.save(total);
                    }
                }
            }

            //根据口径添加部分首检信息

//            List<Bwsjdatail> sjdatailsList = new ArrayList<>();

//            Long maxId2 = bwrkdetailService.getMaxId(BWSJDATAIL);

            Bwsjdatail bsd;

            Map<String, List<Bwrksbdatail>> tableGroup = resultList.stream()
                    .collect(Collectors.groupingBy(b -> b.getBwSbcj() + "-" + b.getBwSbkj() + "-" + b.getBwSblx()));

            Set<String> infoSet = tableGroup.keySet();

            Long msgNumber = 0L;

            for (String info : infoSet) {


                List<String> splitList = Arrays.asList(info.split("-"));
                Long sbcj = StringUtils.isEmpty(splitList.get(0)) ? null : Long.valueOf(splitList.get(0));
                Long sbkj = StringUtils.isEmpty(splitList.get(1)) ? null : Long.valueOf(splitList.get(1));
                Long sblx = StringUtils.isEmpty(splitList.get(2)) ? null : Long.valueOf(splitList.get(2));
                Long cjbl = wareHousingMapper.getCjbl(sbkj);

                if (cjbl > 0) {
                    int num = tableGroup.get(info).size();

                    bsd = new Bwsjdatail();

                    bsd.setBwSbkj(sbkj);
                    bsd.setBwSbcj(sbcj);
                    bsd.setBwSblx(sblx);
                    bsd.setBwPcbh(batch);
                    bsd.setBwRkid(0L);
                    bsd.setBwSbsl(num);
//                    bsd.setId(maxId2);
//                    maxId2++;
                    bsd.setBwCjbl(StringUtils.isEmpty(cjbl) ? "0" : cjbl.toString());
                    bsd.setBwCjsl((long) Math.ceil(num * (cjbl / 100D)));
                    bsd.setCreateUser(userId);
                    bsd.setCreateDate(new Date());

                    bwsjdatailService.save(bsd);
//                    sjdatailsList.add(bsd);
                    msgNumber++;

                }
            }

            if (msgNumber > 0){
                //拥有水表首检菜单权限的人
                List<Long> aubotUser = timedTaskMapper.getAubotUser(104L);

                if (CollectionUtil.isNotEmpty(aubotUser)) {
                    Long msgId = bwrkdetailService.getMaxId(MESSAGE_TABLE_NAME);

                    Messagepush mp = new Messagepush();
                    Messagerecipient mr = new Messagerecipient();
                    mp.setId(msgId);
                    mp.setMessage("当前有" + msgNumber + "批水表待首检");
                    mp.setTopic("水表流转-水表首检");
                    mp.setType("0");
                    mp.setRouteIp("meter/circulation/first");

                    mp.setCreateTime(new Date());
                    mp.setCreateUser(SecurityUtils.getUserId());

                    timedTaskMapper.insertMsg(mp);

                    for (Long users : aubotUser) {
                        mr.setRecipient(users);
                        mr.setMessageId(msgId);
                        mr.setFlag("0");
                        timedTaskMapper.insertMsgStateClient(mr);
                    }
                }
            }
        }

        if (sb.length() == 0) {
            return "";
        } else {
            return sb.deleteCharAt(sb.length() - 1).toString();
        }
    }

    /**
     * 第三层：查看厂家下某个口径某个类型的水表详情
     *
     * @param response response
     * @param page     page
     * @param dto      条件
     * @return page
     */
    @Override
    public Page countByCaliber(HttpServletResponse response, Page page, WareHousingDto dto) {
        Page<Map> mapPage = wareHousingMapper.countByCaliber(page, dto);
        if (dto.getExport() == 1) {
            //导出
            exportCommonCodeService.exportCode(response, "countByCaliberService", mapPage.getRecords());
        }
        return mapPage;
    }

    /**
     * 删除已入库水表
     *
     * @param ids id，多个,分割
     * @return boolean
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteTable(String ids) {
        if (StringUtils.isEmpty(ids)) {
            throw new ToflyDeniedException("传入id为空");
        }
        List<String> idList = Arrays.asList(ids.split(","));

        int count = bwrksbdatailService.count(Wrappers.<Bwrksbdatail>lambdaQuery().eq(Bwrksbdatail::getBwSbzt, 1).in(Bwrksbdatail::getId, idList));

        if (count != idList.size()) {
            throw new ToflyDeniedException("只用入库状态下水表可删除，请重新选择");
        }

        for (String rkid : idList) {
            Bwrksbdatail byId = bwrksbdatailService.getById(rkid);
            if (byId != null && byId.getBwBz() != null) {
                Bwrkdetail tail = bwrkdetailService.getById(byId.getBwBz());
                if (tail != null) {
                    bwrkdetailService.update(Wrappers.<Bwrkdetail>lambdaUpdate()
                            .eq(Bwrkdetail::getId, tail.getId())
                            .set(Bwrkdetail::getBwSl, tail.getBwSl() - 1));
                }
            }
        }
        for (RemoveTableDto dto : wareHousingMapper.queryInfo(idList)) {
            Bwrktotal total = bwrktotalService.getOne(Wrappers.<Bwrktotal>lambdaQuery()
                    .eq(Bwrktotal::getBwSblx, dto.getSblx())
                    .eq(Bwrktotal::getBwSbkj, dto.getSbkj())
                    .eq(Bwrktotal::getBwSbcj, dto.getSbcj()));

            if (total != null) {
                bwrktotalService.update(Wrappers.<Bwrktotal>lambdaUpdate()
                        .eq(Bwrktotal::getId, total.getId())
                        .set(Bwrktotal::getBwKczs, total.getBwKczs() - dto.getNum())
                        .set(Bwrktotal::getBwKcsl, total.getBwKczs() - dto.getNum() - total.getBwSysl()));
            }
        }
        return bwrksbdatailService.removeByIds(idList);
    }

    /**
     * 查询所以信息
     *
     * @param dto dto
     * @return page
     */
    @Override
    public Page getAllInfo(Page page, WareHousingDto dto) {
        return wareHousingMapper.getAllInfo(page, dto);
    }

    /**
     * 根据批次号统计水表信息
     *
     * @param response response
     * @param dto      dto
     * @return list
     */
    @Override
    public Page<Map> countBatchNo(HttpServletResponse response, Page page, WareHousingDto dto) {
        if (dto.getExport() != null && dto.getExport() == 1) {
            exportCommonCodeService.exportCode(response, "batchCountService", wareHousingMapper.countBatchNo(dto));
        }
        return wareHousingMapper.countBatchNo(page, dto);
    }

    @Override
    public Page<Map> batchNoInfo(HttpServletResponse response, Page page, WareHousingDto dto) {
        if (dto.getExport() != null && dto.getExport() == 1) {
            exportCommonCodeService.exportCode(response, "batchInfoService", wareHousingMapper.batchNoInfo(dto));
        }
        return wareHousingMapper.batchNoInfo(page, dto);
    }

}
