package com.prolog.rdc.tms.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.google.common.base.Joiner;
import com.google.common.collect.Lists;
import com.prolog.framework.core.exception.PrologException;
import com.prolog.framework.core.pojo.Page;
import com.prolog.framework.core.restriction.Criteria;
import com.prolog.framework.core.restriction.Order;
import com.prolog.framework.core.restriction.Restriction;
import com.prolog.framework.core.restriction.Restrictions;
import com.prolog.framework.dao.util.PageUtils;
import com.prolog.product.core.framework.entity.UserEntity;
import com.prolog.product.core.framework.util.PlgFxUsrUtils;
import com.prolog.product.core.framework.util.mappercustom.ToolKitsCustom;
import com.prolog.product.core.tools.util.JsonMapper;
import com.prolog.rdc.tms.dao.mapper.ProportionBillStrategyDtlMapper;
import com.prolog.rdc.tms.dao.mapper.ProportionBillStrategyMapper;
import com.prolog.rdc.tms.model.dto.BmsProportionBillStrategyDTO;
import com.prolog.rdc.tms.model.dto.BmsProportionStrategyDetailDTO;
import com.prolog.rdc.tms.model.entity.BmsProportionBillStrategyDtlModel;
import com.prolog.rdc.tms.model.entity.BmsProportionBillStrategyModel;
import com.prolog.rdc.tms.model.vo.BmsProportionStrategyDetailVO;
import com.prolog.rdc.tms.model.vo.BmsProportionStrategyQueryVO;
import com.prolog.rdc.tms.model.vo.BmsProportionStrategyVO;
import com.prolog.rdc.tms.model.vo.StatusUpdate;
import com.prolog.rdc.tms.service.ProportionBillStrategyService;
import org.apache.ibatis.plugin.PluginException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.tools.Tool;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;

@Service
public class ProportionBillStrategyServiceImpl implements ProportionBillStrategyService {

    private final Logger logger = LoggerFactory.getLogger(ProportionBillStrategyServiceImpl.class);

    @Autowired
    private ProportionBillStrategyMapper mapper;
    @Autowired
    private ProportionBillStrategyDtlMapper dtlMapper;

    @Override
    public Page<BmsProportionBillStrategyDTO> findList(BmsProportionStrategyQueryVO vo) {
        UserEntity user = PlgFxUsrUtils.getUserEntity();
        Criteria criteria = Criteria.forClass(BmsProportionBillStrategyModel.class);
        Restriction r1 = ObjectUtil.isEmpty(vo.getStrategyName()) ? null : Restrictions.like("strategyName", "%" + vo.getStrategyName() + "%");
        Restriction r2 = ObjectUtil.isEmpty(vo.getStatus()) ? null : Restrictions.eq("status", vo.getStatus());
        Restriction r3 = Restrictions.eq("enterpriseId", user.getEnterpriseId());
        criteria.setRestriction(Restrictions.and(r1, r2, r3));
        criteria.setOrder(Order.newInstance().desc("updatetime").asc("createtime"));
        PageUtils.startPage(vo.getPageNum(), vo.getPageSize());
        List<BmsProportionBillStrategyModel> models = mapper.findByCriteria(criteria);

        List<BmsProportionBillStrategyDTO> list = Lists.newArrayList();
        for (BmsProportionBillStrategyModel model : models) {
            BmsProportionBillStrategyDTO dto = new BmsProportionBillStrategyDTO();
            BeanUtils.copyProperties(model, dto);
            dto.setStatusName(model.getStatus() == 1 ? "启用" : "停用");
            String feeRule = this.buildFeeRule(model);
            dto.setFeeRule(feeRule);

            if (StrUtil.isNotBlank(model.getRatio())) {
                dto.setRatioStr(model.getRatio());
            } else {
                dto.setRatioStr(model.getRatioNumerator() + "/" + model.getRatioDenominator());
            }
            list.add(dto);
        }
        // 分页设置
        Page<BmsProportionBillStrategyDTO> page = PageUtils.getPage(list);
        if (models instanceof com.github.pagehelper.Page) {
            com.github.pagehelper.Page<BmsProportionBillStrategyModel> p0 = (com.github.pagehelper.Page<BmsProportionBillStrategyModel>) models;
            page.setPageCount(p0.getPages());
            page.setPageNum(p0.getPageNum());
            page.setPageSize(p0.getPageSize());
            page.setTotalCount(p0.getTotal());
            page.setStartRow(p0.getStartRow());
            page.setEndRow(p0.getEndRow());
        }
        return page;
    }

    private String buildFeeRule(BmsProportionBillStrategyModel model) {
        List<String> list = Lists.newArrayList();
        String feeRule = "";
        if (ObjectUtil.isNotEmpty(model.getIsSameBillNo())) {
            int isSameBillNo = model.getIsSameBillNo();
            if (isSameBillNo == 1) {
                list.add("相同订单号");
            }
        }
        if (ObjectUtil.isNotEmpty(model.getIsSameShipbillNo())) {
            int isSameShipbillNo = model.getIsSameShipbillNo();
            if (isSameShipbillNo == 1) {
                list.add("相同运单号");
            }
        }
        if (ObjectUtil.isNotEmpty(model.getIsSameCar())) {
            int isSameCar = model.getIsSameCar();
            if (isSameCar == 1) {
                list.add("相同运输车辆");
            }
        }
        if (ObjectUtil.isNotEmpty(model.getIsSameDriver())) {
            int isSameDriver = model.getIsSameDriver();
            if (isSameDriver == 1) {
                list.add("相同运输司机");
            }
        }
        if (ObjectUtil.isNotEmpty(model.getIsSameElectronicBackDate())) {
            int isSameElectronicBackDate = model.getIsSameElectronicBackDate();
            if (isSameElectronicBackDate == 1) {
                list.add("相同电子回单日期");
            }
        }
        if (ObjectUtil.isNotEmpty(model.getIsSameEndDate())) {
            int isSameEndDate = model.getIsSameEndDate();
            if (isSameEndDate == 1) {
                list.add("相同实际送达日期");
            }
        }
        if (ObjectUtil.isNotEmpty(model.getIsSameOriginalBackDate())) {
            int isSameOriginalBackDate = model.getIsSameOriginalBackDate();
            if (isSameOriginalBackDate == 1) {
                list.add("相同正本回单日期");
            }
        }
        if (ObjectUtil.isNotEmpty(model.getIsSameReceive())) {
            int isSameReceive = model.getIsSameReceive();
            if (isSameReceive == 1) {
                list.add("相同收货方");
            }
        }
        if (ObjectUtil.isNotEmpty(model.getIsSameSender())) {
            int isSameSender = model.getIsSameSender();
            if (isSameSender == 1) {
                list.add("相同发货方");
            }
        }
        if (ObjectUtil.isNotEmpty(model.getIsSameWmsNo())) {
            int isSameWmsNo = model.getIsSameWmsNo();
            if (isSameWmsNo == 1) {
                list.add("相同WMS单号");
            }
        }
        if (ObjectUtil.isNotEmpty(model.getIsStartDate())) {
            int isStartDate = model.getIsStartDate();
            if (isStartDate == 1) {
                list.add("相同实际启运日期");
            }
        }
        if (ObjectUtil.isNotEmpty(model.getIsSameCarrier())) {
            int isSameCarrier = model.getIsSameCarrier();
            if (isSameCarrier == 1) {
                list.add("相同承运商");
            }
        }
        if (ObjectUtil.isNotEmpty(list)) {
            feeRule = Joiner.on(",").join(list);
        }
        return feeRule;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void save(BmsProportionStrategyVO vo) {
        logger.info("新增比例策略信息：" + JSONObject.toJSONString(vo));
        UserEntity user = PlgFxUsrUtils.getUserEntity();

        if ((StrUtil.isBlank(vo.getRatio()) && StrUtil.isBlank(vo.getRatioNumerator())) && StrUtil.isBlank(vo.getRatioDenominator())) {
            throw new PrologException("比例系数,小数和分数至少输入一个");
        }
        if (StrUtil.isNotBlank(vo.getRatio()) && StrUtil.isNotBlank(vo.getRatioNumerator())) {
            throw new PrologException("比例系数,小数和分数只能输入一个");
        }
        if ((StrUtil.isBlank(vo.getRatioNumerator()) && StrUtil.isNotBlank(vo.getRatioDenominator())) ||
                (StrUtil.isNotBlank(vo.getRatioNumerator()) && StrUtil.isBlank(vo.getRatioDenominator()))) {
            throw new PrologException("比例系数,分子和分母必须同时输入");
        }
        if (StrUtil.isNotBlank(vo.getRatioNumerator()) && StrUtil.isNotBlank(vo.getRatioDenominator()) && NumberUtil.isGreater(new BigDecimal(vo.getRatioNumerator()), new BigDecimal(vo.getRatioDenominator()))) {
            throw new PrologException("比例系数,分子的值必须小于分母的值");
        }

        //2 判断流程是否已配置
        Criteria criteria = Criteria.forClass(BmsProportionBillStrategyModel.class);
        Restriction r1 = Restrictions.eq("strategyName", vo.getStrategyName().trim());
        Restriction r2 = Restrictions.eq("enterpriseId", user.getEnterpriseId());
        criteria.setRestriction(Restrictions.and(r1, r2));
        List<BmsProportionBillStrategyModel> list = mapper.findByCriteria(criteria);
        if (ObjectUtil.isNotEmpty(list) && list.size() > 0) {
            throw new RuntimeException(String.format("比例策略名称【%s】已经存在，请不要重复提交", vo.getStrategyName()));
        }
        BmsProportionBillStrategyModel model = new BmsProportionBillStrategyModel();
        BeanUtils.copyProperties(vo, model);
        model.setCreateperson(user.getNickname());
        model.setCreatetime(DateUtil.date());
        model.setUpdateperson(user.getNickname());
        model.setUpdatetime(DateUtil.date());
        model.setEnterpriseId(user.getEnterpriseId());
        model.setEnterpriseName(user.getEnterpriseName());
        model.setStatus(1);
        mapper.insert(model);

        List<BmsProportionStrategyDetailVO> detailVOList = vo.getFlowConditions();
        List<BmsProportionBillStrategyDtlModel> dtlModels = Lists.newArrayList();
        AtomicInteger count = new AtomicInteger(1);
        if (ObjectUtil.isNotEmpty(detailVOList)) {
            for (BmsProportionStrategyDetailVO bmsProportionStrategyDetailVO : detailVOList) {
                BmsProportionBillStrategyDtlModel dtlModel = new BmsProportionBillStrategyDtlModel();
                BeanUtils.copyProperties(bmsProportionStrategyDetailVO, dtlModel);
                dtlModel.setParentId(model.getId());
                dtlModel.setSeqNo(count.get());
                dtlModel.setCreateperson(model.getCreateperson());
                dtlModel.setCreatetime(model.getCreatetime());
                dtlModel.setUpdateperson(model.getUpdateperson());
                dtlModel.setUpdatetime(model.getUpdatetime());
                dtlModel.setEnterpriseId(model.getEnterpriseId());
                dtlModel.setEnterpriseName(model.getEnterpriseName());
                dtlModels.add(dtlModel);

                count.getAndIncrement();
            }

            dtlMapper.saveBatch(dtlModels);
        }
    }

    @Override
    public BmsProportionBillStrategyDTO detail(Long id) {
        if (ObjectUtil.isEmpty(id)) {
            throw new PluginException("查询条件不能为空");
        }
        BmsProportionBillStrategyModel strategyModel = mapper.findById(id, BmsProportionBillStrategyModel.class);
        if (ObjectUtil.isEmpty(strategyModel)) {
            throw new PluginException("获取比例策略为空");
        }
        BmsProportionBillStrategyDTO strategyDTO = new BmsProportionBillStrategyDTO();
        BeanUtils.copyProperties(strategyModel, strategyDTO);
        if (StrUtil.isNotBlank(strategyDTO.getRatio())) {
            strategyDTO.setRatioStr(strategyDTO.getRatio());
        } else {
            strategyDTO.setRatioStr(strategyDTO.getRatioNumerator() + "/" + strategyDTO.getRatioDenominator());
        }
        List<BmsProportionStrategyDetailDTO> list = Lists.newArrayList();
        Map<String, Object> map = new HashMap<>();
        map.put("parentId", strategyModel.getId());
        map.put("enterpriseId", strategyModel.getEnterpriseId());
        List<BmsProportionBillStrategyDtlModel> dtlModels = dtlMapper.findByMap(map, BmsProportionBillStrategyDtlModel.class);
        for (BmsProportionBillStrategyDtlModel dtlModel : dtlModels) {
            BmsProportionStrategyDetailDTO dto = new BmsProportionStrategyDetailDTO();
            BeanUtils.copyProperties(dtlModel, dto);
            list.add(dto);
        }
        strategyDTO.setFlowConditions(list);
        return strategyDTO;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(BmsProportionStrategyVO vo) {
        if (ObjectUtil.isEmpty(vo.getId())) {
            throw new PluginException("修改参数不能为空");
        }
        if ((StrUtil.isBlank(vo.getRatio()) && StrUtil.isBlank(vo.getRatioNumerator())) && StrUtil.isBlank(vo.getRatioDenominator())) {
            throw new PrologException("比例系数,小数和分数至少输入一个");
        }
        if (StrUtil.isNotBlank(vo.getRatio()) && StrUtil.isNotBlank(vo.getRatioNumerator())) {
            throw new PrologException("比例系数,小数和分数只能输入一个");
        }
        if ((StrUtil.isBlank(vo.getRatioNumerator()) && StrUtil.isNotBlank(vo.getRatioDenominator())) ||
                (StrUtil.isNotBlank(vo.getRatioNumerator()) && StrUtil.isBlank(vo.getRatioDenominator()))) {
            throw new PrologException("比例系数,分子和分母必须同时输入");
        }
        if (StrUtil.isNotBlank(vo.getRatioNumerator()) && StrUtil.isNotBlank(vo.getRatioDenominator()) && NumberUtil.isGreater(new BigDecimal(vo.getRatioNumerator()), new BigDecimal(vo.getRatioDenominator()))) {
            throw new PrologException("比例系数,分子的值必须小于分母的值");
        }

        BmsProportionBillStrategyModel model = mapper.findById(vo.getId(), BmsProportionBillStrategyModel.class);
        if (ObjectUtil.isEmpty(model)) {
            throw new PluginException("查询合并策略数据不存在");
        }
        UserEntity user = PlgFxUsrUtils.getUserEntity();
        BeanUtils.copyProperties(vo, model);
        model.setUpdateperson(user.getNickname());
        model.setUpdatetime(DateUtil.date());
        model.setStatus(model.getStatus());
        mapper.update(model);

        // 删除明细
        Map<String, Object> map = new HashMap<>();
        map.put("parentId", model.getId());
        map.put("enterpriseId", model.getEnterpriseId());
        dtlMapper.deleteByMap(map, BmsProportionBillStrategyDtlModel.class);

        // 新增
        List<BmsProportionStrategyDetailVO> detailVOList = vo.getFlowConditions();
        List<BmsProportionBillStrategyDtlModel> dtlModels = Lists.newArrayList();
        if (ObjectUtil.isNotEmpty(detailVOList)) {
            for (BmsProportionStrategyDetailVO bmsProportionStrategyDetailVO : detailVOList) {
                BmsProportionBillStrategyDtlModel dtlModel = new BmsProportionBillStrategyDtlModel();
                BeanUtils.copyProperties(bmsProportionStrategyDetailVO, dtlModel);
                dtlModel.setId(null);
                dtlModel.setParentId(model.getId());
                dtlModel.setCreateperson(model.getCreateperson());
                dtlModel.setCreatetime(model.getCreatetime());
                dtlModel.setUpdateperson(model.getUpdateperson());
                dtlModel.setUpdatetime(model.getUpdatetime());
                dtlModel.setEnterpriseId(model.getEnterpriseId());
                dtlModel.setEnterpriseName(model.getEnterpriseName());
                dtlModels.add(dtlModel);
            }
            dtlMapper.saveBatch(dtlModels);
        }
    }

    @Override
    public void updateStatus(List<StatusUpdate> vo) {
        logger.info("- > updateStatus vo={}", JsonMapper.toJsonString(vo));
        // 1 校验数据
        if (ObjectUtil.isEmpty(vo)) {
            throw new RuntimeException("请求参数不能为空");
        }
        UserEntity user = PlgFxUsrUtils.getUserEntity();
        for (StatusUpdate statusUpdate : vo) {
            BmsProportionBillStrategyModel model = mapper.findById(statusUpdate.getId(), BmsProportionBillStrategyModel.class);
            model.setStatus(statusUpdate.getStatus());
            model.setUpdateperson(user.getNickname());
            model.setUpdatetime(DateUtil.date());
            mapper.update(model);
        }
    }

    @Override
    public void delete(String[] ids) {
        if (ObjectUtil.isEmpty(ids)) {
            throw new RuntimeException("请求参数不能为空");
        }
        // 判断是否启用
        for (String id : ids) {
            BmsProportionBillStrategyModel model = mapper.findById(id, BmsProportionBillStrategyModel.class);
            if (model.getStatus() == 1) {
                throw new PluginException(String.format("拆分策略[%s],是启用状态不能删除", model.getStrategyName()));
            }

            mapper.deleteById(id, BmsProportionBillStrategyModel.class);

            Map<String, Object> map = new HashMap<>();
            map.put("parentId", model.getId());
            map.put("enterpriseId", model.getEnterpriseId());
            dtlMapper.deleteByMap(map, BmsProportionBillStrategyDtlModel.class);

        }
    }
}