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

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.tofly.api.CodeClient;
import com.tofly.common.core.entity.ResultRespone;
import com.tofly.common.core.util.Date8Util;
import com.tofly.common.core.util.DateUtil;
import com.tofly.common.core.util.StringUtil;
import com.tofly.common.oauth.exception.ToflyDeniedException;
import com.tofly.pojo.Syschildcode;
import com.tofly.watermeter.custom.entity.Statistic;
import com.tofly.watermeter.custom.service.SbPlanService;
import com.tofly.watermeter.custom.util.Date7Utils;
import com.tofly.watermeter.em.Constant;
import com.tofly.watermeter.em.ExcelExportFileTypeEnum;
import com.tofly.watermeter.entity.Bwkjzjpz;
import com.tofly.watermeter.entity.Qfkhjbxx;
import com.tofly.watermeter.service.BwkjzjpzService;
import com.tofly.watermeter.service.BwsbzjdatailService;
import com.tofly.watermeter.service.QfkhjbxxService;
import com.tofly.watermeter.strategy.ExcelStrategyContext;
import com.tofly.watermeter.util.ExcelUtil;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * @author FlashWJL
 * @date 2021/3/24 13:49
 */
@AllArgsConstructor
@Service
public class SbPlanServiceImpl implements SbPlanService {

    private final QfkhjbxxService qfkhjbxxService;
    private final BwsbzjdatailService zjService;
    private final CodeClient client;
    private final BwkjzjpzService bwkjzjpzService;
    private final ExcelStrategyContext excelStrategyContext;


    @Override
    public IPage<Qfkhjbxx> getPlan(Page<Qfkhjbxx> page, Statistic statistic, HttpServletResponse response) {
        String templateFlag = statistic.getTemplateFlag();
        String sbkj = statistic.getSbkj();
        String sblx = statistic.getSblx();
        String sbcj = statistic.getSbcj();
        String startMonth = statistic.getStartMonth();
        String endMonth = statistic.getEndMonth();
        if (StringUtil.isEmpty(startMonth) || StringUtil.isEmpty(endMonth)) {
            throw new ToflyDeniedException("请选择月份日期");
        }
        IPage<Qfkhjbxx> qfkhjbxxIPage = qfkhjbxxService.page(page, Wrappers.<Qfkhjbxx>lambdaQuery()
                .eq(StringUtil.isNotEmpty(sbkj), Qfkhjbxx::getSbkj, sbkj).eq(StringUtil.isNotEmpty(sblx), Qfkhjbxx::getSblx, sblx)
                .eq(StringUtil.isNotEmpty(sbcj), Qfkhjbxx::getSbcj, sbcj).between(Qfkhjbxx::getXcZjrq, startMonth, endMonth)
                .select(Qfkhjbxx::getYhbh, Qfkhjbxx::getSbbh, Qfkhjbxx::getSbkj, Qfkhjbxx::getSblx, Qfkhjbxx::getSbcj, Qfkhjbxx::getYhdz,
                        Qfkhjbxx::getLxdh, Qfkhjbxx::getAzrq, Qfkhjbxx::getXcZjrq, Qfkhjbxx::getYhxm));
        if ("1".equals(templateFlag)) {
            //如果传的是 1，则代表导出Excel数据
            // 根据templateServiceType,templateFlag获取对应模板数据
            ExcelExportFileTypeEnum excelExportFileTypeEnum =
                    ExcelExportFileTypeEnum.getExcelExportFileTypeEnum("zjsbService", templateFlag);
            if (null == excelExportFileTypeEnum) {
                return null;
            }
            List<Qfkhjbxx> mapList = qfkhjbxxIPage.getRecords();
            //将查询的结果转json字符串的格式，因为导出的时候只能传一个字符串
            String resultListToString = JSONArray.toJSONStringWithDateFormat(mapList, "yyyy-MM-dd");
            // 从模型类型枚举根据templateServiceType获取策略对应模板数据
            List<Map<String, Object>> dataList = excelStrategyContext.getExportData("zjsbService", templateFlag, resultListToString);
            ExcelUtil.export(dataList.get(0), excelExportFileTypeEnum, Constant.FILE_PATH_TEST_EXPORT_EXCEL, response);
            return null;
        } else {
            return qfkhjbxxIPage;
        }
    }

//    @Override
//    public Page getPlanInfo(Page page, String month, String sbcj, String sblx, String sbkj) {
//        //厂家、类型、口径信息
//        ResultRespone respone = client.getBylistPcid("1,2,3");
//        List<CustomCode> codeList = JSONObject.parseArray(JSONObject.toJSONString(respone.getResult()), CustomCode.class);
//        Map<Long, CustomCode> map = new HashMap<>();
//        codeList.forEach(k -> {
//            map.put(k.getId(), k);
//        });
//        Map<String, String> cj = map.get(2L).getCodeList().stream().collect(Collectors.toMap(Syschildcode::getCcode, Syschildcode::getCname));
//        Map<String, String> kj = map.get(1L).getCodeList().stream().collect(Collectors.toMap(Syschildcode::getCcode, Syschildcode::getCname));
//        Map<String, String> lx = map.get(3L).getCodeList().stream().collect(Collectors.toMap(Syschildcode::getCcode, Syschildcode::getCname));
//        Page<Bwsbzjdatail> page1 = zjService.page(page, Wrappers.<Bwsbzjdatail>lambdaQuery().eq(Bwsbzjdatail::getBwZjyf, month)
//                .eq(StringUtil.isNotEmpty(sblx), Bwsbzjdatail::getBwSblx, sblx)
//                .eq(StringUtil.isNotEmpty(sbcj), Bwsbzjdatail::getBwSbcj, sbcj)
//                .eq(StringUtil.isNotEmpty(sbkj), Bwsbzjdatail::getBwSbkj, sbkj));
//
//        page1.getRecords().forEach(k -> {
//            k.setSbcjName(cj.get(k.getBwSbcj()));
//            k.setSbkjName(kj.get(k.getBwSbkj()));
//            k.setSblxName(lx.get(k.getBwSblx()));
//        });
//
//
//        return page1;
//    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean generateReckonZj() {
        //检查到期水表
        //首先查询所有周检配置情况
        List<Bwkjzjpz> kjPzList = bwkjzjpzService.list();
        //存放下次周检的用户信息
        List<Qfkhjbxx> zjKhList = new ArrayList<>();
        //查询对应口径，普通表类型客户
        kjPzList.forEach(v -> {
            List<Qfkhjbxx> qfkhjbxxList = null;
            String csCode = v.getCsCode();
            Integer month = v.getMonth();
            String isCommon = v.getIsCommon();
            String csFlag = v.getCsFlag();
            //普通表类型，根据口径判断
            if ("0".equals(csFlag)) {
                //只能是普通表不是电子表类型的水表，然后根据口径推算周检时间
                qfkhjbxxList = qfkhjbxxService.list(Wrappers.<Qfkhjbxx>lambdaQuery()
                        .eq(StringUtil.isNotEmpty(isCommon), Qfkhjbxx::getSblx, isCommon)
                        .eq(Qfkhjbxx::getSbkj, csCode)
                        .select(Qfkhjbxx::getYhbh, Qfkhjbxx::getAzrq));
            }
            //根据电子表类型（远传表、卡表、物联网表）推算周检日期
            else {
                qfkhjbxxList = qfkhjbxxService.list(Wrappers.<Qfkhjbxx>lambdaQuery().eq(Qfkhjbxx::getSblx, csCode)
                        .select(Qfkhjbxx::getYhbh, Qfkhjbxx::getAzrq));
            }
            //计算对应客户的水表周检日期
            for (Qfkhjbxx qfkh : qfkhjbxxList) {
                //安装日期
                Date azrq = qfkh.getAzrq();
                if (StringUtil.isNotNull(azrq)) {
                    //计算下次周检日期
                    Date zjrq = Date7Utils.addNextPeriod(month, azrq);
                    String zjrqStr = DateUtil.parseDateToStr("yyyyMM", zjrq);
                    qfkh.setXcZjrq(zjrqStr);
                    zjKhList.add(qfkh);
                }
            }
        });
        //太长了  导致无法修改
        int size = zjKhList.size();
        //向上取整 , 获得次数，但是次数不多，只有几次，所以可以使用for循环分段查询
        int count = (int) Math.ceil(Double.valueOf(size) / 1000d);
        //一个区域段最多1000多条数据，所以这里最多循环两次
        for (int i = 0; i < count; i++) {
            int startIndex = i * 1000;
            int endIndex = 1000 + (i * 1000);
            List<Qfkhjbxx> subList = new ArrayList<>();
            //判断是否截取的最后一次数据，如果是最后一次数据，则不能使用endIndex这个参数去截取了，有可能会存在endIndex参数值超过索引最大值的情况
            if (i < count - 1) {
                //分段采取数据 0~999 ； 1000~1999 , 2000~2999 .....//这里subList方法无法截取最后一位，所以需要多写一位索引
                subList = zjKhList.subList(startIndex, endIndex);
            } else {
                //分段采取最后的数据
                subList = zjKhList.subList(startIndex, zjKhList.size());
            }
            //修改客户下次周检日期
            zjService.updateZjKh(subList);
        }
        return true;
    }

    @Override
    public List<Map> getYearMonth() {
        return zjService.getYearMonth();
    }

    @Override
    public boolean sbzqConfig(Bwkjzjpz bwkjzjpz) {
        Long id = bwkjzjpz.getId();
        Integer month = bwkjzjpz.getMonth();
        String csFlag = bwkjzjpz.getCsFlag();
        String csCode = bwkjzjpz.getCsCode();
        String sbzjCs = bwkjzjpz.getSbzjCs();
        if (StringUtil.isNull(month)){
            throw new ToflyDeniedException("请输入到期月份");
        }
        if (StringUtil.isEmpty(sbzjCs)){
            throw new ToflyDeniedException("请选择周检判断条件");
        }
        if (StringUtil.isEmpty(csCode)){
            throw new ToflyDeniedException("请传入周检判断条件对应code编码");
        }
        if (StringUtil.isEmpty(csFlag)){
            throw new ToflyDeniedException("请选择周检判断条件类型：水表口径或类型");
        }
        //如果传了ID则表示修改
        if (StringUtil.isNotNull(id)){
            bwkjzjpzService.update(Wrappers.<Bwkjzjpz>lambdaUpdate().eq(Bwkjzjpz::getId, id)
                    .set(Bwkjzjpz::getMonth, month));
        }else {
            //判断是否已经有相同配置
            int count = bwkjzjpzService.count(Wrappers.<Bwkjzjpz>lambdaQuery().eq(Bwkjzjpz::getSbzjCs , sbzjCs));
            if (count > 0){
                throw new ToflyDeniedException("已有该配置，请勿重复添加");
            }
            //如果是水表口径判断类型的，则必须要普通表的编码code
            if ("0".equals(csFlag)){
                Syschildcode syschildcode = new Syschildcode();
                syschildcode.setCname("普通表");
                syschildcode.setPcid(3L);
                ResultRespone resultRespone = client.getChild(syschildcode);
                List<Syschildcode> codeList = JSONObject.parseArray(JSONObject.toJSONString(resultRespone.getResult()), Syschildcode.class);
                //可以很肯定，只有能查找到水表类型下普通表只有一个
                syschildcode = codeList.get(0);
                String commonCode = syschildcode.getCcode();
                bwkjzjpz.setIsCommon(commonCode);
            }
            //新增
            bwkjzjpzService.save(bwkjzjpz);
        }
        return true;
    }

    @Override
    public IPage sbzqQuery(Page<Bwkjzjpz> page) {
        return bwkjzjpzService.page(page);
    }

}
