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.watermeter.custom.entity.meterBusiness.dto.OutBoundDto;
import com.tofly.watermeter.custom.entity.meterBusiness.dto.OutBoundInfo;
import com.tofly.watermeter.custom.entity.meterBusiness.dto.RemoveTableDto;
import com.tofly.watermeter.custom.mapper.meterBusiness.OutBoundMapper;
import com.tofly.watermeter.custom.service.meterBusiness.OutBoundService;
import com.tofly.watermeter.custom.service.meterBusiness.export.ExportCommonCodeService;
import com.tofly.watermeter.entity.Bwckdatail;
import com.tofly.watermeter.entity.Bwgdandck;
import com.tofly.watermeter.entity.Bwrksbdatail;
import com.tofly.watermeter.service.BwckdatailService;
import com.tofly.watermeter.service.BwgdandckService;
import com.tofly.watermeter.service.BwrksbdatailService;
import lombok.AllArgsConstructor;
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
@AllArgsConstructor
public class OutBoundServiceImpl implements OutBoundService {
    private final OutBoundMapper outBoundMapper;
    private final BwrksbdatailService bwrksbdatailService;
    private final BwckdatailService bwckdatailService;
    private final BwgdandckService bwgdandckService;
    private final ExportCommonCodeService exportCommonCodeService;

    private final static Integer MAX_IN_QUERY_NUM = 1000;

    /**
     * 出库工单统计
     *
     * @param response response
     * @param page     page
     * @param dto      条件
     * @return page
     */
    @Override
    public Page count(HttpServletResponse response, Page page, OutBoundDto dto) {
        if (dto.getExport() == 1) {
            //导出
            List<Map> listInfo = outBoundMapper.count(dto);

            if (CollectionUtil.isNotEmpty(listInfo)) {
                listInfo.forEach(m -> {
                    String codes = String.valueOf(m.get("codes"));
                    if (!StringUtils.isEmpty(codes)) {
                        m.put("tableNum", outBoundMapper.outBoundCount(codes));
                    }
                });
            }

            exportCommonCodeService.exportCode(response, "outBoundCountService", listInfo);
        }
        Page<Map> result = outBoundMapper.count(page, dto);
        List<Map> records = result.getRecords();
        if (CollectionUtil.isNotEmpty(records)) {
            records.forEach(m -> {
                String codes = String.valueOf(m.get("codes"));
                if (!StringUtils.isEmpty(codes)) {
                    m.put("tableNum", outBoundMapper.outBoundCount(codes));
                }
            });
        }
        return result;
    }

    /**
     * 工单详情统计
     *
     * @param response response
     * @param page     page
     * @param dto      条件
     * @return page
     */
    @Override
    public Page countByWorkOrder(HttpServletResponse response, Page page, OutBoundDto dto) {
        if (dto.getExport() == 1) {
            //导出
            List<Map> listInfo = outBoundMapper.countByWorkOrder(dto);
            exportCommonCodeService.exportCode(response, "outBoundCountWorkOrderService", listInfo);
        }
        return outBoundMapper.countByWorkOrder(page, dto);
    }

    /**
     * 查询工单水表详细信息
     *
     * @param response response
     * @param page     page
     * @param dto      dto
     * @return page
     */
    @Override
    public Page queryTableInfo(HttpServletResponse response, Page page, OutBoundDto dto) {

        if (dto == null) {
            throw new ToflyDeniedException("传入条件不能为空");
        }
        if (StringUtils.isEmpty(dto.getCode())) {
            throw new ToflyDeniedException("工单编号不允许为空");
        }

        List<Bwgdandck> bwgdandcks = bwgdandckService.list(Wrappers.<Bwgdandck>lambdaQuery()
                .eq(Bwgdandck::getGdid, dto.getCode()));

        List<Long> ckIdList = bwgdandcks.stream().map(Bwgdandck::getSkid).collect(Collectors.toList());

        String start = dto.getStart();
        String end = dto.getEnd();

        if (dto.getExport() == 1) {
            exportCommonCodeService.exportCode(response, "outBoundTableInfoService", outBoundMapper.queryTableInfo(ckIdList, start, end));
        }
        return outBoundMapper.queryTableInfo(page, ckIdList, start, end);
    }


    /**
     * 水表出库
     *
     * @param dto 数据
     * @return Boolean
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean tableOutBound(OutBoundInfo dto) {
        if (StringUtils.isEmpty(dto.getSbbh())) {
            throw new ToflyDeniedException("水表编号不允许为空");
        }
        if (StringUtils.isEmpty(dto.getGdbh())) {
            throw new ToflyDeniedException("工单编号不允许为空");
        }

        Long workOrderCode = outBoundMapper.getWorkOrderCode(dto.getGdbh());

        if (workOrderCode == null) {
            throw new ToflyDeniedException("工单编号：" + dto.getGdbh() + " 工单不存在");
        }

        if (workOrderCode != 45) {
            throw new ToflyDeniedException("工单：" + dto.getGdbh() + "未进行审核，不能出库");
        }

        List<String> codeList = Arrays.stream(dto.getSbbh().split(",")).distinct().collect(Collectors.toList());

//        List<RemoveTableDto> countInfo = new ArrayList<>();

        List<Bwrksbdatail> rkList = new ArrayList<>();

        List<RemoveTableDto> countInfo = outBoundMapper.getCountInfo(codeList);

        int codeSize = codeList.size();
        if (codeSize <= MAX_IN_QUERY_NUM) {
            List<Bwrksbdatail> resList = bwrksbdatailService.list(Wrappers.<Bwrksbdatail>lambdaQuery()
                    .and(v -> v.eq(Bwrksbdatail::getBwSbzt, 1).or().eq(Bwrksbdatail::getBwSbzt, 8))
                    .in(Bwrksbdatail::getBwSbbh, codeList)
                    .select(Bwrksbdatail::getBwSbcj, Bwrksbdatail::getBwSblx, Bwrksbdatail::getBwSbkj, Bwrksbdatail::getBwSbbh));
            rkList.addAll(resList);
        } else {
            int number = (int) Math.ceil((float) codeSize / MAX_IN_QUERY_NUM);
            //截取下标范围
            int startIndex;
            int endIndex;

            for (int i = 1; i <= number; i++) {
                startIndex = (i - 1) * MAX_IN_QUERY_NUM;
                if (i == number) {
                    endIndex = codeSize;
                } else {
                    endIndex = i * MAX_IN_QUERY_NUM;
                }
                List<String> subList = codeList.subList(startIndex, endIndex);

                List<Bwrksbdatail> resList = bwrksbdatailService.list(Wrappers.<Bwrksbdatail>lambdaQuery()
                        .and(v -> v.eq(Bwrksbdatail::getBwSbzt, 1).or().eq(Bwrksbdatail::getBwSbzt, 8))
                        .in(Bwrksbdatail::getBwSbbh, subList)
                        .select(Bwrksbdatail::getBwSbcj, Bwrksbdatail::getBwSblx, Bwrksbdatail::getBwSbkj, Bwrksbdatail::getBwSbbh));
                rkList.addAll(resList);
            }

        }

        //收集查出的水表编号，用作比较入库水表看是否有不在库中的数据
        List<String> sbbhLit = rkList.stream().map(Bwrksbdatail::getBwSbbh).collect(Collectors.toList());

        String nonentity = codeList.stream().filter(c -> !sbbhLit.contains(c)).collect(Collectors.joining(","));

        if (!StringUtils.isEmpty(nonentity)) {
            throw new ToflyDeniedException("请检查编号" + nonentity + "水表是否存在异常");
        }

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

        Bwckdatail tail;

        Bwgdandck bwgdandck;

        String date = DateUtil.getDateFormat(new Date(), "yyyyMMdd") + "-" + System.currentTimeMillis();

        for (RemoveTableDto table : countInfo) {
            tail = new Bwckdatail();

            tail.setBwLsbh(date);
            tail.setBwLqry(dto.getLbry());
            tail.setBwLqbm(dto.getLbbm());
            tail.setBwSl(table.getNum());
            tail.setContract(dto.getContract());
            tail.setMeterUse(dto.getMeterUse());
            tail.setContractCode(dto.getContractCode());
            tail.setBwSbcj(table.getSbcj());
            tail.setBwSbkj(table.getSbkj());
            tail.setBwSblx(table.getSblx());
            if (!StringUtils.isEmpty(dto.getCkbz())) {
                tail.setBwBz(dto.getCkbz());
            }
            bwckdatailService.save(tail);

            String str = table.getSbcj() + "-" + table.getSblx() + "-" + table.getSbkj();

            List<String> sbbhList = collect.get(str).stream()
                    .map(Bwrksbdatail::getBwSbbh).collect(Collectors.toList());

            int size = sbbhList.size();

            if (size <= MAX_IN_QUERY_NUM) {
                bwrksbdatailService.update(Wrappers.<Bwrksbdatail>lambdaUpdate()
                        .in(Bwrksbdatail::getBwSbbh, sbbhList)
                        .set(Bwrksbdatail::getBwSbzt, 2)
                        .set(Bwrksbdatail::getCkId, tail.getId()));
            } else {
                int number = (int) Math.ceil((float) size / MAX_IN_QUERY_NUM);
                //截取下标范围
                int startIndex;
                int endIndex;

                for (int i = 1; i <= number; i++) {
                    startIndex = (i - 1) * MAX_IN_QUERY_NUM;
                    if (i == number) {
                        endIndex = size;
                    } else {
                        endIndex = i * MAX_IN_QUERY_NUM;
                    }
                    List<String> subList = sbbhList.subList(startIndex, endIndex);
                    bwrksbdatailService.update(Wrappers.<Bwrksbdatail>lambdaUpdate()
                            .in(Bwrksbdatail::getBwSbbh, subList)
                            .set(Bwrksbdatail::getBwSbzt, 2)
                            .set(Bwrksbdatail::getCkId, tail.getId()));
                }
            }
            bwgdandck = new Bwgdandck();
            bwgdandck.setGdid(dto.getGdbh());
            bwgdandck.setSkid(tail.getId());

            bwgdandckService.save(bwgdandck);
        }
        return outBoundMapper.updateWorkOrder(dto.getGdbh());
    }

    @Override
    public Page<Map> getWareHousinginfo(Page page, OutBoundDto dto) {
        return outBoundMapper.getWareHousinginfo(page, dto);
    }

    @Override
    public List<Bwckdatail> getCkCount(String code) {

        List<Bwckdatail> result = null;

        List<Bwgdandck> bwgdandck = bwgdandckService.list(Wrappers.<Bwgdandck>lambdaQuery()
                .eq(Bwgdandck::getGdid, code));

        if (!bwgdandck.isEmpty()) {
            List<Long> skidList = bwgdandck.stream()
                    .map(Bwgdandck::getSkid).collect(Collectors.toList());
            result = bwckdatailService.list(Wrappers.<Bwckdatail>lambdaQuery()
                    .in(Bwckdatail::getId, skidList));
        }

        return result;
    }

    /**
     * 异常表处理
     *
     * @param code code
     * @return list
     */
    @Override
    public List<String> abnormalTables(String code) {
        if (StringUtils.isEmpty(code)) {
            throw new ToflyDeniedException("表编号为空");
        }
        List<String> codeList = Arrays.stream(code.split(",")).distinct().collect(Collectors.toList());


        int size = codeList.size();
        List<String> list = new ArrayList<>();

        if (size <= MAX_IN_QUERY_NUM) {
            List<String> collect = bwrksbdatailService.list(Wrappers.<Bwrksbdatail>lambdaQuery()
                    .in(Bwrksbdatail::getBwSbbh, codeList)
                    .and(v -> v.eq(Bwrksbdatail::getBwSbzt, 1).or().eq(Bwrksbdatail::getBwSbzt, 8)))
                    .stream()
                    .map(Bwrksbdatail::getBwSbbh)
                    .collect(Collectors.toList());
            list.addAll(collect);
        } else {
            int number = (int) Math.ceil((float) size / MAX_IN_QUERY_NUM);
            //截取下标范围
            int startIndex;
            int endIndex;

            for (int i = 1; i <= number; i++) {
                startIndex = (i - 1) * MAX_IN_QUERY_NUM;
                if (i == number) {
                    endIndex = size;
                } else {
                    endIndex = i * MAX_IN_QUERY_NUM;
                }
                List<String> subList = codeList.subList(startIndex, endIndex);
                List<String> collect = bwrksbdatailService.list(Wrappers.<Bwrksbdatail>lambdaQuery()
                        .in(Bwrksbdatail::getBwSbbh, subList)
                        .and(v -> v.eq(Bwrksbdatail::getBwSbzt, 1).or().eq(Bwrksbdatail::getBwSbzt, 8)))
                        .stream()
                        .map(Bwrksbdatail::getBwSbbh)
                        .collect(Collectors.toList());
                list.addAll(collect);
            }
        }

        return codeList.stream().filter(c -> !list.contains(c)).collect(Collectors.toList());
    }

    /**
     * 获取所有合同信息
     *
     * @return list
     */
    @Override
    public List<String> getContractInfo() {
        return bwckdatailService.list(Wrappers.<Bwckdatail>lambdaQuery()
                .isNotNull(Bwckdatail::getContract).or().isNotNull(Bwckdatail::getContractCode))
                .stream().filter(Objects::nonNull).distinct().map(r -> r.getContract() + r.getContractCode())
                .collect(Collectors.toList());
    }
}
