package com.dxhy.jxpt.baseService.cpyAuthInvoice.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.dxhy.api.model.config.UserInfo;
import com.dxhy.api.model.config.sys.SysEnterpriseConfigEntity;
import com.dxhy.api.model.cpy.cpyCustom.TDxRecordCustomCpyVo;
import com.dxhy.api.model.cpy.pageImport.CpyImportCustomReq;
import com.dxhy.api.model.custom.TdxCustomsRecord;
import com.dxhy.api.model.db.TdxCustomsCpyGxEntity;
import com.dxhy.api.model.db.TdxCustomsDetailEntity;
import com.dxhy.api.model.db.TdxCustomsRecordEntity;
import com.dxhy.api.model.db.TdxSpbmCpyHgshEntity;
import com.dxhy.common.constant.ConfigureConstant;
import com.dxhy.common.constant.DictConstant;
import com.dxhy.common.service.DictdetaServcice;
import com.dxhy.common.service.TabulateRedisService;
import com.dxhy.common.service.impl.MpBaseServiceImpl;
import com.dxhy.common.util.AmountFormatUtil;
import com.dxhy.common.util.MathUtil;
import com.dxhy.common.utils.DateUtils;
import com.dxhy.common.utils.R;
import com.dxhy.jxpt.baseService.config.dao.SysEnterpriseConfigDao;
import com.dxhy.jxpt.baseService.cpyAuthInvoice.dao.CpyRecordCustomDao;
import com.dxhy.jxpt.baseService.cpyAuthInvoice.service.CpyAuthCustomService;
import com.dxhy.jxpt.baseService.dao.TdxCustomsCpyGxDao;
import com.dxhy.jxpt.baseService.dao.TdxCustomsDetailDao;
import com.dxhy.jxpt.baseService.dao.TdxSpbmCpyHgshDao;
import com.dxhy.jxpt.baseService.rzInvoice.dao.TdxCustomsRecordDao;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.text.DecimalFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Description 成品油缴款书勾选业务
 * @Author wangruwei
 * @Date 2024/7/12 10:10
 **/
@Service("cpyAuthCustomService")
@Slf4j
public class CpyAuthCustomServiceImpl extends MpBaseServiceImpl<CpyRecordCustomDao, TdxCustomsRecordEntity> implements CpyAuthCustomService {

    @Resource
    private TdxSpbmCpyHgshDao tdxSpbmCpyHgshDao;

    @Resource
    private TdxCustomsCpyGxDao tdxCustomsCpyGxDao;

    @Resource
    private CpyRecordCustomDao cpyRecordCustomDao;


    @Resource
    private TdxCustomsRecordDao tdxCustomsRecordDao;

    @Resource
    private TdxCustomsDetailDao tdxCustomsDetailDao;


    @Resource
    private SysEnterpriseConfigDao sysEnterpriseConfigDao;


    @Resource
    private DictdetaServcice dictdetaServcice;

    @Resource
    private TabulateRedisService tabulateRedisService;


    /**
     * @Description 成品油缴款书勾选-页面查询接口
     * @param pramsMap
     * @Return java.lang.Object
     * @Author wangruwei
     * @Date 2024/7/12 10:42
     **/
    @Override
    public Object selectAuthPageList(Map<String, Object> pramsMap, int curr, int size) {
        JSONObject json = new JSONObject();
        try {
            String company = (String)pramsMap.get("company");
            String menuId = (String)pramsMap.get("menuId");
            json = tabulateRedisService.getTabulateMenu(company, menuId);
            // 合计信息,仅第一页时需要统计，减少数据库压力
            if (curr == 1) {

                String hjsl = "0";
                String hjse = "0.00";
                List<TDxRecordCustomCpyVo> hjList = super.baseMapper.selectAuthPageListHj(pramsMap);
                TDxRecordCustomCpyVo hjxx = hjList.get(0);
                hjsl = hjxx.getHjsl();
                if (!"0".equals(hjsl)) {
                    hjse = AmountFormatUtil.fmtMicrometer(MathUtil.round(hjxx.getHjse()));
                }
                json.put("hjsl", hjsl);
                json.put("hjse", hjse);
            }

            PageHelper.startPage(curr, size);
            List<TDxRecordCustomCpyVo> pageList = super.baseMapper.selectAuthPageList(pramsMap);
            PageInfo<TDxRecordCustomCpyVo> pageInfo = new PageInfo<>(pageList);
            List<TDxRecordCustomCpyVo> resultList = pageInfo.getList();
            // 用于页面返回list对象
            if (resultList.size() > 0) {
                int start = (int)pageInfo.getStartRow();
                for (int i = 0; i < resultList.size(); i++) {
                    resultList.get(i).setXh(String.valueOf(i + start));

                    pageList.get(i)
                            .setSelect(true);
                    //设置是否可勾选
                    String notAllowCheck = getCheckedStatus(resultList.get(i));
                    if(StringUtils.isNotBlank(notAllowCheck)){
                        pageList.get(i)
                                .setSelect(false);
                        pageList.get(i)
                                .setNotAllowCheckStr(notAllowCheck);
                    }

                    if(ObjectUtil.isNotEmpty(resultList.get(i).getTaxAmount())){
                        resultList.get(i).setTaxAmount(
                                AmountFormatUtil.fmtMicrometer(MathUtil.round(resultList.get(i).getTaxAmount()) ));
                    }
                    //重号锁定
                    resultList.get(i).setLqSfchsd(dictdetaServcice.queryDictName(DictConstant.CUSTOM_SFCHSD, resultList.get(i).getLqSfchsd()));

                    //消费税用途
                    resultList.get(i).setLqXfsyt(dictdetaServcice.queryDictName(DictConstant.XFSYT, resultList.get(i).getLqXfsyt()));

                    //用途处理状态
                    resultList.get(i).setGxclzt(dictdetaServcice.queryDictName(DictConstant.CPY_GXCLZT, resultList.get(i).getGxclzt()));
                }
            }
            // 设置记录总数
            json.put("total", pageInfo.getTotal());
            json.put("datalist", resultList);
            if("0".equals(pramsMap.get("tabNum"))||"3".equals(pramsMap.get("tabNum"))){
                json.put("selection", true);
            }
            json.put("tabNum", pramsMap.get("tabNum"));
        } catch (Exception e) {
            // 统一设置操作异常标识
            json = super.errorResult(e);
        }
        return super.responseResult(json);
    }
    /**
     * @Description 成品油状态-页面状态统计接口
     * @Return java.lang.Object
     * @Author wangruwei
     * @Date 2024/7/12 10:42
     *
     * @param pramsMap*/
    @Override
    public Object selectCountStatusPage(Map<String, Object> pramsMap) {
        List<TdxCustomsCpyGxEntity> customsCpyGxList = cpyRecordCustomDao.selectCountStatusPage(pramsMap);
        //筛选出进行中 状态是1,2，失败的数据 状态是3
        int ingCount = customsCpyGxList.stream().filter(e -> "1".equals(e.getGxclzt()) || "2".equals(e.getGxclzt())).collect(Collectors.toList()).size();
        int failCount = customsCpyGxList.stream().filter(e -> "3".equals(e.getGxclzt())).collect(Collectors.toList()).size();
        JSONObject json = new JSONObject();
        json.put("ingCount",ingCount>999?"999+":ingCount);
        json.put("failCount",failCount>999?"999+":failCount);
        return super.responseResult(json);
    }


    /**
     * @Description 成品油状态-选中缴款书提示勾选总吨数
     * @param
     * @Return java.lang.Object
     * @Author wangruwei
     * @Date 2024/7/16 17:09
     **/
    @Override
    public Object selCustomCount(List<String> customList) {
        //查找缴款书明细数据
        List<TdxCustomsDetailEntity> detailList = tdxCustomsDetailDao.selectList(new LambdaQueryWrapper<TdxCustomsDetailEntity>()
                .in(TdxCustomsDetailEntity::getCustomsCode, customList));
        log.info("缴款书对应的所有明细数量:{}",detailList.size());
        //查找成品油税编
        List<TdxSpbmCpyHgshEntity> spbmCpyList = tdxSpbmCpyHgshDao.selectList(null);
        //商品编码列表-海关税号
        List<String> spbmList = spbmCpyList.stream().map(TdxSpbmCpyHgshEntity::getHgsh).collect(Collectors.toList());
        //筛选出编码对应的名称  海关税号--名称
        Map<String, String> spBmToMc = spbmCpyList.stream().collect(Collectors.toMap(
                TdxSpbmCpyHgshEntity::getHgsh,
                TdxSpbmCpyHgshEntity::getHwmc,
                (existing, replacement) -> existing // 如果key重复，保留第一个value
        ));
        log.info("成品油海关税号编码数据查询完成");

        //筛选出属于成品油的明细，按海关税号分组  海关税号--明细list
        Map<String, List<TdxCustomsDetailEntity>> groupSpbm = detailList.stream().filter(e -> spbmList.contains(e.getTaxno()))
                .collect(Collectors.groupingBy(TdxCustomsDetailEntity::getTaxno));
        log.info("筛选完属于成品油的明细，共{}种",groupSpbm.size());

        JSONObject json = new JSONObject();
        //汇总出展示到前端的数据
        Map<String,Object> resultMap = new HashMap();
        groupSpbm.keySet().forEach(key -> {
            List<TdxCustomsDetailEntity> tdxRecordCustomsDetailEntities = groupSpbm.get(key);
            TdxSpbmCpyHgshEntity tdxSpbmCpyCustomsEntity = spbmCpyList.stream().filter(e -> key.equals(e.getHgsh())).findFirst().get();
            if(tdxRecordCustomsDetailEntities.size()>0){
                resultMap.put(spBmToMc.get(key),sumDetailCount(tdxRecordCustomsDetailEntities,tdxSpbmCpyCustomsEntity)+"吨" );
            }
        });

        json.put("selNum", customList.size());
        json.put("selGroup", resultMap);

        //统计出各项的总数
        return super.responseResult(json);
    }

    /**
     * @Description 成品油批量勾选入库接口
     * @Return java.lang.Object
     * @Author wangruwei
     * @Date 2024/7/16 14:25
     **/
    @Override
    public Object cpyGxByCustoms(List<String> uuidList, UserInfo userInfo) {
        //页面可勾选，现在直接判断t_dx_invoice_cpy_gx里的状态，可勾选的入库
        List<TdxCustomsCpyGxEntity> tdxInvoiceCpyGxEntities = tdxCustomsCpyGxDao.selectList(new LambdaQueryWrapper<TdxCustomsCpyGxEntity>()
                .in(TdxCustomsCpyGxEntity::getGxclzt,Arrays.asList("0","3"))
                .in(TdxCustomsCpyGxEntity::getCustomsCode, uuidList));
        log.info("筛选出状态为0和3的数据，更新为勾选中,筛选出要更新的数据{}条",tdxInvoiceCpyGxEntities.size());
        if(tdxInvoiceCpyGxEntities.size()>0){
            List<String> updateCustomsList = tdxInvoiceCpyGxEntities.stream().map(TdxCustomsCpyGxEntity::getCustomsCode).collect(Collectors.toList());
            TdxCustomsCpyGxEntity updateCpygx = new TdxCustomsCpyGxEntity();
            updateCpygx.setGxclzt("1");
            updateCpygx.setCzr(userInfo.getId());
            updateCpygx.setCzrName(userInfo.getUsername());
            updateCpygx.setCzsj(new Date());
            int update = tdxCustomsCpyGxDao.update(updateCpygx, new LambdaUpdateWrapper<TdxCustomsCpyGxEntity>()
                    .in(TdxCustomsCpyGxEntity::getCustomsCode, updateCustomsList));
            log.info("更新完成，本次更新{}条",update);
        }else{
            log.info("没有要更新的数据");
        }

        JSONObject json = new JSONObject();
        json.put("code","0000");
        json.put("message","处理成功");
        return super.responseResult(json);
    }



    /**
     * @Description 成品油全部勾选入库接口--根据页面查询条件提示勾选总吨数
     * @param
     * @Return java.lang.Object
     * @Author wangruwei
     * @Date 2024/7/16 17:09
     **/
    @Override
    public Map<String,Object> cpyGxBySelConditionCount(Map<String, Object> pramsMap) {
        Map<String,Object> result = new HashMap();
        //找到所有符合条件的数据
        List<TDxRecordCustomCpyVo> selList = super.baseMapper.selectAuthPageList(pramsMap);
        log.info("页面条件查询出条数:{}",selList.size());
        //筛选出可勾选的数据uuid集合
        List<String> customsList = selList.stream().filter(e -> StringUtils.isBlank(getCheckedStatus(e))).map(TDxRecordCustomCpyVo::getCustomsCode).collect(Collectors.toList());
        log.info("其中可勾选的数量:{}",customsList.size());
        if(customsList.size()==0){
            result.put("code", "9998");
            result.put("msg", "没有可勾选数据");
            return result;
        }
        log.info("调勾选显示吨数方法，获取数据");
        result.put("code", "0000");
        result.put("data", selCustomCount(customsList));
        return result;
    }

    /**
     * @Description 成品油全部勾选入库接口--根据页面查询条件全部勾选
     * @param pramsMap
     * @param userInfo
     * @Return java.lang.Object
     * @Author wangruwei
     * @Date 2024/7/16 14:25
     **/
    @Override
    public Object cpyGxBySelCondition(Map<String, Object> pramsMap, UserInfo userInfo) {
        //找到所有符合条件的数据
        List<TDxRecordCustomCpyVo> selList = super.baseMapper.selectAuthPageList(pramsMap);
        log.info("页面条件查询出条数:{}",selList.size());
        //筛选出可勾选的数据uuid集合
        List<String> customsList = selList.stream().filter(e -> StringUtils.isBlank(getCheckedStatus(e))).map(TDxRecordCustomCpyVo::getCustomsCode).collect(Collectors.toList());
        log.info("其中可勾选的数量:{}",customsList.size());
        log.info("调勾选入库方法");
        return cpyGxByCustoms(customsList, userInfo);
    }

    /**
     * @Description 成品油导入勾选-缴款书
     * @param cpyImportCustomsReqList
     * @param gfshAll
     * @Return java.lang.Object
     * @Author wangruwei
     * @Date 2024/7/17 10:43
     **/
    @Override
    public ResponseEntity<R> cpyImportCustom(List<CpyImportCustomReq> cpyImportCustomsReqList, UserInfo userInfo, List<String> gfshAll) {
        //验证数据是否合法
        List<String> errorMsgList = checkDrParam(cpyImportCustomsReqList,gfshAll);
        if (!CollectionUtils.isEmpty(errorMsgList)) {
            log.info("参数校验未通过");
            return ResponseEntity.ok(R.error(9998, "参数校验未通过").put("data", errorMsgList));
        }
        //筛选出uuid集合
        List<String> customsList = cpyImportCustomsReqList.stream().map(e -> e.getCustomsCode()).collect(Collectors.toList());
        
        log.info("调导入勾选方法");
        cpyGxByCustoms(customsList,userInfo);
        log.info("调查询勾选各项吨数，给到前端");
        Object gxSucData = selCustomCount(customsList);
        log.info("导入勾选完成");
        return ResponseEntity.ok(R.ok().put("data", gxSucData));

    }


    //-------------------------------方法部分-----------------------------------------------------------------------------------

    /**
    * @Description 格式化吨，变为千分位，小数后面的0去掉
    * @param dunStr
    * @Return java.lang.String
    * @Author wangruwei
    * @Date 2024/7/17 15:10
    **/
    public static String formateDunNumStr(String dunStr){
        // 将字符串转换为双精度浮点数
        double number = Double.parseDouble(dunStr);

        // 创建DecimalFormat实例，设置格式
        DecimalFormat df = new DecimalFormat("#,##0.##########");

        // 格式化数字并返回结果
        return df.format(number);
    }

    public static void main(String[] args) {
        System.out.println(formateDunNumStr("123456.12345600"));
    }

    private List<String> checkDrParam(List<CpyImportCustomReq> reqList, List<String> gfshAll) {
        int index = 0;
        List<String> errorMsgList = new ArrayList<>();
        for (CpyImportCustomReq param : reqList) {
            String error = null;
            index ++;
            String customsCode = param.getCustomsCode();
            String tfrq = param.getTfrq();
            if (StringUtils.isBlank(customsCode)) {
                error = "第"+index+ "条数据：缴款书号码必填";
                log.info("error");
                errorMsgList.add(error);
                continue;
            }

            if (StringUtils.isBlank(tfrq)) {
                error = "第"+index+ "条数据：填发日期必填";
                log.info("error");
                errorMsgList.add(error);
                continue;
            }
            if(!DateUtils.checkStrFormat(tfrq, "yyyy-MM-dd")){
                error = "第"+index+ "条数据：开票日期格式不正确";
                log.info("error");
                errorMsgList.add(error);
                continue;
            }
            //1.3.校验海关缴款书号码+填开日期与抵账库中比对是否存在，如果不存在则返回“海关缴款书不存在”
            TdxCustomsRecord customsRecord = tdxCustomsRecordDao.selectOne(new LambdaQueryWrapper<TdxCustomsRecord>()
                    .eq(TdxCustomsRecord::getCustomsCode, customsCode)
                    .likeRight(TdxCustomsRecord::getFillInDate, tfrq)
            );

            if (customsRecord == null) {
                error = "第"+index+ "条数据：底账库不存在该缴款书";
                log.info("error");
                errorMsgList.add(error);
                continue;
            }

            //1.4.校验发票对应购方税号是否为当前用户权限，如果不满足则返回“无海关缴款书所属税号操作权限”
            SysEnterpriseConfigEntity enterpriseConfig = sysEnterpriseConfigDao.selectOne(new QueryWrapper<SysEnterpriseConfigEntity>().eq("nsrsbh", customsRecord.getGfTaxNo()));
            if (enterpriseConfig == null) {
                error = "第"+index+ "条数据：未查询到该购方税号："+customsRecord.getGfTaxNo()+"的配置信息";
                log.info("error");
                errorMsgList.add(error);
                continue;
            }

            //1.4.校验发票对应购方税号是否为当前用户权限，如果不满足则返回“无海关缴款书所属税号操作权限”
            if (!enterpriseConfig.getJrfs().equals(ConfigureConstant.STRING_1)) {
                error = "第"+index+ "条数据：该购方税号：："+customsRecord.getGfTaxNo()+"为非乐企税号不支持成品油勾选";
                log.info("error");
                errorMsgList.add(error);
                continue;
            }

            if(!gfshAll.contains(customsRecord.getGfTaxNo())){
                error = "第"+index+ "条数据：无缴款书所属税号操作权限";
                log.info("error");
                errorMsgList.add(error);
                continue;
            }

            //1.5.校验海关缴款书是否为成品油海关缴款书，校验明细编码--勾选表有数据，则为成品油
            TdxCustomsCpyGxEntity tdxInvoiceCpyGxEntity = tdxCustomsCpyGxDao.selectOne(new LambdaQueryWrapper<TdxCustomsCpyGxEntity>().eq(TdxCustomsCpyGxEntity::getCustomsCode, customsRecord.getCustomsCode()));
            if (ObjectUtil.isEmpty(tdxInvoiceCpyGxEntity)) {
                error = "第"+index+ "条数据：非成品油缴款书不允许导入";
                log.info("error");
                errorMsgList.add(error);
                continue;
            }

            //1.6.校验成品油消费税用途是否为 未勾选库存（或者判断系统中的用途处理状态是否为未申请、申请失败）否则返回“发票当前发票已在处理中、已勾选入库，不可重复提交勾选入库”
            if("1".equals(tdxInvoiceCpyGxEntity.getGxclzt())||"2".equals(tdxInvoiceCpyGxEntity.getGxclzt())||"4".equals(tdxInvoiceCpyGxEntity.getGxclzt())){
                error = "第"+index+ "条数据：当前缴款书已做入库操作，不允许重复勾选入库";
                log.info("error");
                errorMsgList.add(error);
                continue;
            }

            //1.7.校验海关缴款书是否重号未锁定，如果为锁定则返回“海关缴款书已重号锁定”
            if("Y".equals(customsRecord.getLqSfchsd())){
                error = "第"+index+ "条数据：海关缴款书已重号锁定";
                log.info("error");
                errorMsgList.add(error);
                continue;
            }
        }
        return errorMsgList;
    }

    /**
    * @Description 计算明细里成品油吨数
    * @param detailList     缴款书明细表--同一个税编的明细集合
    * @param spbmCpyHgshEntity    成品油税编表
    * @Return void
    * @Author wangruwei
    * @Date 2024/7/16 17:45
    **/
    public static String sumDetailCount(List<TdxCustomsDetailEntity> detailList,TdxSpbmCpyHgshEntity spbmCpyHgshEntity){
        //总吨数
        String totalDun = "0";
        //计量单位换算标准（升/千克）
        String jldwhs = spbmCpyHgshEntity.getJldwhs();
        for (int i = 0; i < detailList.size(); i++) {
            TdxCustomsDetailEntity detailItem = detailList.get(i);
            if(StringUtils.isNotBlank(detailItem.getNum())){
                if("升".equals(detailItem.getUnit())){
                    //变成吨
                    String itemDun = MathUtil.divide(MathUtil.divide(detailItem.getNum(), jldwhs,6), "1000",6);
                    totalDun = MathUtil.add(totalDun, itemDun);
                }else if("吨".equals(detailItem.getUnit())){
                    totalDun = MathUtil.add(totalDun, detailItem.getNum());
                }else{
                    //不处理
                }
            }
        }
        if("0".equals(totalDun)){
            return "0";
        }else{
            return formateDunNumStr(totalDun);
        }
    }

    /**
    * @Description 获取当前缴款书可勾选状态
    * @param TDxRecordCustomCpyVo
     * @Return void
    * @Author wangruwei
    * @Date 2024/7/15 17:59
    **/
    private String getCheckedStatus(TDxRecordCustomCpyVo TDxRecordCustomCpyVo) {
        //不可选原因
        List<String> notSelMsg = new LinkedList();

        if("Y".equals(TDxRecordCustomCpyVo.getLqSfchsd())){
            notSelMsg.add("重号锁定");
        }

        String showStr = String.join(",", notSelMsg);
        if(StringUtils.isNotBlank(showStr)){
            showStr+="。不允许勾选库存";
        }
        return showStr;
    }
}
