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

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.UUID;
import cn.hutool.core.util.ObjectUtil;
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.rdc.tms.constant.BmsConstant;
import com.prolog.rdc.tms.constant.enums.ContractModeEnum;
import com.prolog.rdc.tms.dao.mapper.*;
import com.prolog.rdc.tms.model.dto.ContractLogQueryDTO;
import com.prolog.rdc.tms.model.dto.LogisticsContractDTO;
import com.prolog.rdc.tms.model.dto.LogisticsContractQuery;
import com.prolog.rdc.tms.model.entity.*;
import com.prolog.rdc.tms.model.vo.BmsShipBillDTO;
import com.prolog.rdc.tms.model.vo.ContractLogQueryVO;
import com.prolog.rdc.tms.model.vo.LogisticsContractVO;
import com.prolog.rdc.tms.model.vo.StatusUpdate;
import com.prolog.rdc.tms.service.LogisticsContractService;
import com.prolog.rdc.tms.service.ShipCostStrategyService;
import com.prolog.rdc.tms.util.ConvertorUtil;
import org.apache.ibatis.plugin.PluginException;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class LogisticsContractServiceImpl implements LogisticsContractService {

    @Autowired
    private LogisticsContractMapper mapper;
    @Autowired
    private ShipBillHeadMapper shipBillHeadMapper;
    @Autowired
    private ShipBillDetailMapper shipBillDetailMapper;
    @Autowired
    private ShipCostStrategyService shipCostStrategyService;
    @Autowired
    private ConvertorUtil convertorUtil;
    @Autowired
    private BmsLogOperationMapper logOperationMapper;
    @Autowired
    private FreightPriceMapper priceMapper;
    @Autowired
    private BmsFreightPriceConditionMapper conditionMapper;
    @Autowired
    private FreightPriceLadderMapper ladderMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void save(LogisticsContractVO vo) {
        if (ObjectUtil.isNull(vo.getContractMode())) {
            vo.setContractMode(ContractModeEnum.SHIPPER.getCode());
        }
        UserEntity user = PlgFxUsrUtils.getUserEntity();
        // 1.判断合同编号是否存在
        Criteria criteria = Criteria.forClass(BmsLogisticsContractModel.class);
        Restriction r1 = Restrictions.eq("contractNo", vo.getContractNo());
        Restriction r2 = Restrictions.eq("enterpriseId", user.getEnterpriseId());
        criteria.setRestriction(Restrictions.and(r1, r2));
        List<BmsLogisticsContractModel> managementModels = mapper.findByCriteria(criteria);
        if (ObjectUtil.isNotEmpty(managementModels)) {
            throw new PluginException(String.format("合同编码[%s]已存在，请不要重复添加", vo.getContractNo()));
        }
        // 2.判断合同名称是否存在
        Criteria nCriteria = Criteria.forClass(BmsLogisticsContractModel.class);
        Restriction r3 = Restrictions.eq("contractName", vo.getContractName());
        Restriction r4 = Restrictions.eq("enterpriseId", user.getEnterpriseId());
        nCriteria.setRestriction(Restrictions.and(r3, r4));
        List<BmsLogisticsContractModel> models = mapper.findByCriteria(nCriteria);
        if (ObjectUtil.isNotEmpty(models)) {
            throw new PluginException(String.format("合同名称[%s]已存在，请不要重复添加", vo.getContractName()));
        }
        vo.setId(null);
        BmsLogisticsContractModel model = new BmsLogisticsContractModel();
        BeanUtils.copyProperties(vo, model);
        model.setCreateperson(user.getNickname());
        model.setCreatetime(DateUtil.date());
        model.setUpdatetime(DateUtil.date());
        model.setUpdateperson(user.getNickname());
        model.setEnterpriseId(user.getEnterpriseId());
        model.setEnterpriseName(user.getEnterpriseName());
        model.setStatus(2);
        mapper.save(model);

        BmsLogOperationModel feeVo = new BmsLogOperationModel();
        feeVo.setCreatetime(DateUtil.date());
        feeVo.setCreateperson(user.getNickname());
        feeVo.setEnterpriseId(user.getEnterpriseId());
        feeVo.setEnterpriseName(user.getEnterpriseName());
        feeVo.setOrderNo(model.getContractNo());
        feeVo.setLogMemo("价格合同生成");
        feeVo.setLogType(2);
        logOperationMapper.save(feeVo);
    }

    @Override
    public Page<LogisticsContractDTO> findList(LogisticsContractQuery vo) {
        if (ObjectUtil.isNull(vo.getContractMode())) {
            vo.setContractMode(ContractModeEnum.SHIPPER.getCode());
        }
        UserEntity user = PlgFxUsrUtils.getUserEntity();
        vo.setEnterpriseId(user.getEnterpriseId());
        if (ObjectUtil.isNotEmpty(vo.getFirstPartyName())) {
            String[] firstPartyNameArr = vo.getFirstPartyName().split(",");
            vo.setFirstPartyNames(Arrays.stream(firstPartyNameArr).collect(Collectors.toList()));
        }
        if (ObjectUtil.isNotEmpty(vo.getSecondPartyName())) {
            String[] secondPartyNameArr = vo.getSecondPartyName().split(",");
            vo.setSecondPartyNames(Arrays.stream(secondPartyNameArr).collect(Collectors.toList()));
        }
        PageUtils.startPage(vo.getPageNum(), vo.getPageSize());
        List<LogisticsContractDTO> models = mapper.queryLogisticsContract(vo);

        List<SysRefdatadModel> dicData = convertorUtil.getDictionary(new String[]{
                BmsConstant.CONTRACT_TYPE,
                BmsConstant.CONTRACT_STATUS,
                BmsConstant.FIRST_PARTY_TYPE,
                BmsConstant.SECOND_PARTY_TYPE,
                BmsConstant.SETTLEMENT_WAY
        });
        List<LogisticsContractDTO> dtos = Lists.newArrayList();
        for (LogisticsContractDTO dto : models) {
            dto.setContractStatus(ConvertorUtil.getName(dicData, BmsConstant.CONTRACT_STATUS, String.valueOf(dto.getStatus())));
            dto.setContractTypeName(ConvertorUtil.getName(dicData, BmsConstant.CONTRACT_TYPE, String.valueOf(dto.getContractType())));
            dto.setSettlementTypeName(ConvertorUtil.getName(dicData, BmsConstant.SETTLEMENT_WAY, String.valueOf(dto.getSettlementType())));
            dto.setFirstPartyTypeName(ConvertorUtil.getName(dicData, BmsConstant.FIRST_PARTY_TYPE, String.valueOf(dto.getFirstPartyType())));
            dto.setSecondPartyTypeName(ConvertorUtil.getName(dicData, BmsConstant.SECOND_PARTY_TYPE, String.valueOf(dto.getSecondPartyType())));
            dto.setIsHeavyBubbleName(dto.getIsHeavyBubble().intValue() == 1 ? "是" : "否");
            dtos.add(dto);
        }
        Page<LogisticsContractDTO> page = PageUtils.getPage(dtos);
        if (models instanceof com.github.pagehelper.Page) {
            com.github.pagehelper.Page<LogisticsContractDTO> p0 = (com.github.pagehelper.Page<LogisticsContractDTO>) 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;
    }

    @Override
    public LogisticsContractDTO detail(Long id) {
        if (ObjectUtil.isEmpty(id)) {
            throw new PluginException("查询条件不能为空");
        }
        BmsLogisticsContractModel managementModel = mapper.findById(id, BmsLogisticsContractModel.class);
        if (ObjectUtil.isEmpty(managementModel)) {
            throw new PluginException("查询详情信息为空");
        }
        List<SysRefdatadModel> dicData = convertorUtil.getDictionary(new String[]{
                BmsConstant.CONTRACT_TYPE,
                BmsConstant.CONTRACT_STATUS,
                BmsConstant.SETTLEMENT_WAY
        });
        LogisticsContractDTO dto = new LogisticsContractDTO();
        BeanUtils.copyProperties(managementModel, dto);
        dto.setContractStatus(ConvertorUtil.getName(dicData, BmsConstant.CONTRACT_STATUS, String.valueOf(dto.getStatus())));
        dto.setContractTypeName(ConvertorUtil.getName(dicData, BmsConstant.CONTRACT_TYPE, String.valueOf(dto.getContractType())));
        dto.setSettlementTypeName(ConvertorUtil.getName(dicData, BmsConstant.SETTLEMENT_WAY, String.valueOf(dto.getSettlementType())));
        return dto;
    }

    @Override
    public void update(LogisticsContractVO vo) {
        UserEntity user = PlgFxUsrUtils.getUserEntity();
        BmsLogisticsContractModel managementModel = mapper.findById(vo.getId(), BmsLogisticsContractModel.class);
        if (ObjectUtil.isEmpty(managementModel)) {
            throw new PluginException("查询详情信息为空");
        }
        BeanUtils.copyProperties(vo, managementModel);
        managementModel.setUpdateperson(user.getNickname());
        managementModel.setUpdatetime(DateUtil.date());
        managementModel.setEnterpriseId(user.getEnterpriseId());
        managementModel.setEnterpriseName(user.getEnterpriseName());
        mapper.update(managementModel);

        BmsLogOperationModel feeVo = new BmsLogOperationModel();
        feeVo.setCreatetime(DateUtil.date());
        feeVo.setCreateperson(user.getNickname());
        feeVo.setEnterpriseId(user.getEnterpriseId());
        feeVo.setEnterpriseName(user.getEnterpriseName());
        feeVo.setOrderNo(managementModel.getContractNo());
        feeVo.setLogMemo("价格合同修改");
        feeVo.setLogType(2);
        logOperationMapper.save(feeVo);
    }

    @Override
    public void copy(LogisticsContractVO vo) {
        UserEntity user = PlgFxUsrUtils.getUserEntity();
        if (ObjectUtil.isEmpty(vo.getOrigContractNo())) {
            throw new PrologException("复制的元合同编号不为空");
        }
        // 1.判断合同编号是否存在
        Criteria criteria = Criteria.forClass(BmsLogisticsContractModel.class);
        Restriction r1 = Restrictions.like("contractNo", vo.getContractNo());
        Restriction r2 = Restrictions.eq("enterpriseId", user.getEnterpriseId());
        criteria.setRestriction(Restrictions.and(r1, r2));
        List<BmsLogisticsContractModel> managementModels = mapper.findByCriteria(criteria);
        if (ObjectUtil.isNotEmpty(managementModels)) {
            throw new PluginException(String.format("合同编码[%s]已存在，请不要重复添加", vo.getContractNo()));
        }
        // 2.判断合同名称是否存在
        Criteria nCriteria = Criteria.forClass(BmsLogisticsContractModel.class);
        Restriction r3 = Restrictions.like("contractName", vo.getContractName());
        Restriction r4 = Restrictions.eq("enterpriseId", user.getEnterpriseId());
        nCriteria.setRestriction(Restrictions.and(r3, r4));
        List<BmsLogisticsContractModel> models = mapper.findByCriteria(nCriteria);
        if (ObjectUtil.isNotEmpty(models)) {
            throw new PluginException(String.format("合同名称[%s]已存在，请不要重复添加", vo.getContractName()));
        }
        BmsLogisticsContractModel model = new BmsLogisticsContractModel();
        BeanUtils.copyProperties(vo, model);
        model.setId(null);
        model.setCreateperson(user.getNickname());
        model.setCreatetime(DateUtil.date());
        model.setUpdatetime(DateUtil.date());
        model.setUpdateperson(user.getNickname());
        model.setEnterpriseId(user.getEnterpriseId());
        model.setEnterpriseName(user.getEnterpriseName());
        mapper.save(model);

        // 价格表同时复制过来
        Criteria criteriaPrice = Criteria.forClass(BmsFreightPriceModel.class);
        Restriction r5 = Restrictions.eq(BmsFreightPriceModel::getContractNo, vo.getOrigContractNo());
        Restriction r6 = Restrictions.eq(BmsFreightPriceModel::getEnterpriseId, user.getEnterpriseId());
        criteriaPrice.setRestriction(Restrictions.and(r5, r6));
        List<BmsFreightPriceModel> priceModels = priceMapper.findByCriteria(criteriaPrice);
        if (ObjectUtil.isNotEmpty(priceModels)) {
            for (BmsFreightPriceModel copyPriceModel : priceModels) {
                String priceNo = UUID.fastUUID().toString();
                // 1.运费价格
                BmsFreightPriceModel priceModel = new BmsFreightPriceModel();
                BeanUtils.copyProperties(copyPriceModel, priceModel);
                priceModel.setId(null);
                priceModel.setContractNo(vo.getContractNo());
                priceModel.setPriceNo(priceNo);
                priceModel.setPriceName(copyPriceModel.getPriceName() + "复制1");
                priceModel.setCreateperson(user.getNickname());
                priceModel.setCreatetime(DateUtil.date());
                priceModel.setUpdatetime(DateUtil.date());
                priceModel.setUpdateperson(user.getNickname());
                priceModel.setEnterpriseId(user.getEnterpriseId());
                priceModel.setEnterpriseName(user.getEnterpriseName());
                priceMapper.save(priceModel);
                // 查询匹配条件
                Criteria aClass = Criteria.forClass(BmsFreightPriceConditionModel.class);
                r5 = Restrictions.eq(BmsFreightPriceConditionModel::getPriceNo, copyPriceModel.getPriceNo());
                aClass.setRestriction(Restrictions.and(r5, r6));
                List<BmsFreightPriceConditionModel> conditionModels = conditionMapper.findByCriteria(aClass);
                if (ObjectUtil.isNotEmpty(conditionModels)) {
                    for (BmsFreightPriceConditionModel copyConditionModel : conditionModels) {
                        // 2.价格的匹配条件
                        BmsFreightPriceConditionModel conditionModel = new BmsFreightPriceConditionModel();
                        BeanUtils.copyProperties(copyConditionModel, conditionModel);
                        conditionModel.setId(null);
                        conditionModel.setPriceNo(priceNo);
                        conditionModel.setCreateperson(user.getNickname());
                        conditionModel.setCreatetime(DateUtil.date());
                        conditionModel.setUpdatetime(DateUtil.date());
                        conditionModel.setUpdateperson(user.getNickname());
                        conditionModel.setEnterpriseId(user.getEnterpriseId());
                        conditionModel.setEnterpriseName(user.getEnterpriseName());
                        conditionMapper.save(conditionModel);
                    }
                }
                // 查询阶梯条件
                Criteria lClass = Criteria.forClass(BmsFreightPriceLadderModel.class);
                lClass.setRestriction(Restrictions.and(r5, r6));
                List<BmsFreightPriceLadderModel> ladderModels = ladderMapper.findByCriteria(lClass);
                if (ObjectUtil.isNotEmpty(ladderModels)) {
                    for (BmsFreightPriceLadderModel copyLadderModel : ladderModels) {
                        BmsFreightPriceLadderModel ladderModel = new BmsFreightPriceLadderModel();
                        BeanUtils.copyProperties(copyLadderModel, ladderModel);
                        ladderModel.setId(null);
                        ladderModel.setPriceNo(priceNo);
                        ladderModel.setCreateperson(user.getNickname());
                        ladderModel.setLadderType(copyLadderModel.getLadderType() + "复制1");
                        ladderModel.setCreatetime(DateUtil.date());
                        ladderModel.setUpdatetime(DateUtil.date());
                        ladderModel.setUpdateperson(user.getNickname());
                        ladderModel.setEnterpriseId(user.getEnterpriseId());
                        ladderModel.setEnterpriseName(user.getEnterpriseName());
                        if (ObjectUtil.isEmpty(ladderModel.getFirstHour())) {
                            ladderModel.setFirstHour(BigDecimal.ZERO);
                        }
                        ladderMapper.save(ladderModel);
                    }
                }
            }
        }
        BmsLogOperationModel feeVo = new BmsLogOperationModel();
        feeVo.setCreatetime(DateUtil.date());
        feeVo.setCreateperson(user.getNickname());
        feeVo.setEnterpriseId(user.getEnterpriseId());
        feeVo.setEnterpriseName(user.getEnterpriseName());
        feeVo.setOrderNo(model.getContractNo());
        feeVo.setLogMemo("价格合同复制");
        feeVo.setLogType(2);
        logOperationMapper.save(feeVo);
    }

    @Override
    public void updateStatus(List<StatusUpdate> list) {
        // 1 校验数据
        if (ObjectUtil.isEmpty(list)) {
            throw new RuntimeException("请求参数不能为空");
        }
        UserEntity user = PlgFxUsrUtils.getUserEntity();
        for (StatusUpdate statusUpdate : list) {
            BmsLogisticsContractModel managementModel = mapper.findById(statusUpdate.getId(), BmsLogisticsContractModel.class);
            if (managementModel.getStatus() == 0 && statusUpdate.getStatus() == 0) {
                throw new PluginException(String.format("合同[%s]已经停用", managementModel.getContractName()));
            }
            if (managementModel.getStatus() == 1 && statusUpdate.getStatus() == 1) {
                throw new PluginException(String.format("合同[%s]已启用", managementModel.getContractName()));
            }
            if (managementModel.getStatus() == 2 && statusUpdate.getStatus() == 0) {
                throw new PluginException("仅支持合同启用状态下停用！");
            }
            managementModel.setStatus(statusUpdate.getStatus());
            managementModel.setUpdateperson(user.getNickname());
            managementModel.setUpdatetime(DateUtil.date());
            mapper.update(managementModel);
//            if (statusUpdate.getStatus() == 1) {
//                // 查询当前审批节点
//                ApprovalOpenVO approvalOpenVO = new ApprovalOpenVO();
//                approvalOpenVO.setApprovalFlowType(BmsConstant.APPROVAL_FLOW_TYPE_CONTRACT);
//                approvalOpenVO.setApprovalObjectId(String.valueOf(managementModel.getId()));
//                approvalOpenVO.setApprovalObjectCode(managementModel.getContractNo());
//                approvalOpenVO.setApprovalObjectName(managementModel.getContractName());
//                approvalOpenVO.setInitiatedUserId(user.getUserid());
//                approvalOpenVO.setInitiatedUserName(user.getNickname());
//
//                // 判断是否有承运商审核流
//                RestMessage<Boolean> booleanRestMessage = maindataFeign.openExecute(approvalOpenVO);
//                if (ObjectUtil.isNotEmpty(booleanRestMessage) && booleanRestMessage.getData()) {
//                    // 状态改为审核中
//                    managementModel.setStatus(BmsConstant.STATUS_UNDER_REVIEW);
//                    managementModel.setUpdatetime(DateUtil.date());
//                    managementModel.setUpdateperson(user.getNickname());
//                    mapper.update(managementModel);
//
//                    // 生成临时表数据
//                    // mapper.save(model);
//                } else {
//                    // 没有审核流直接修改为启用状态
//                    managementModel.setStatus(1);
//                    managementModel.setUpdatetime(DateUtil.date());
//                    managementModel.setUpdateperson(user.getNickname());
//                    mapper.update(managementModel);
//                }
//            }else {
//                managementModel.setStatus(statusUpdate.getStatus());
//                managementModel.setUpdatetime(DateUtil.date());
//                managementModel.setUpdateperson(user.getNickname());
//                mapper.update(managementModel);
//            }

            BmsLogOperationModel feeVo = new BmsLogOperationModel();
            feeVo.setCreatetime(DateUtil.date());
            feeVo.setCreateperson(user.getNickname());
            feeVo.setEnterpriseId(user.getEnterpriseId());
            feeVo.setEnterpriseName(user.getEnterpriseName());
            feeVo.setOrderNo(managementModel.getContractNo());
            if (managementModel.getStatus() == 0) {
                feeVo.setLogMemo("价格合同停用");
            } else {
                feeVo.setLogMemo("价格合同启用");
            }
            feeVo.setLogType(2);
            logOperationMapper.save(feeVo);
        }
    }

    @Override
    public void trialTest(Long id) {
        // 1 校验数据
        if (ObjectUtil.isEmpty(id)) {
            throw new RuntimeException("请求参数不能为空");
        }
        UserEntity user = PlgFxUsrUtils.getUserEntity();
        BmsShipBillHeaderModel model = shipBillHeadMapper.findById(id, BmsShipBillHeaderModel.class);
        Criteria criteria = Criteria.forClass(BmsShipBillDetailModel.class);
        Restriction r1 = Restrictions.eq("shipbillNo", model.getShipbillNo());
        Restriction r2 = Restrictions.eq("enterpriseId", user.getEnterpriseId());
        criteria.setRestriction(Restrictions.and(r1, r2));
        List<BmsShipBillDetailModel> models = shipBillDetailMapper.findByCriteria(criteria);
        BmsShipBillDTO dto = new BmsShipBillDTO();
        dto.setDetailModelList(models);
        dto.setModel(model);
        // 0：试验，1：非试验
        shipCostStrategyService.costStrategy(dto, "0");

        BmsLogOperationModel feeVo = new BmsLogOperationModel();
        feeVo.setCreatetime(DateUtil.date());
        feeVo.setCreateperson(user.getNickname());
        feeVo.setEnterpriseId(user.getEnterpriseId());
        feeVo.setEnterpriseName(user.getEnterpriseName());
        feeVo.setOrderNo(model.getShipbillNo());
        feeVo.setLogMemo("运单试算实验");
        feeVo.setLogType(1);
        logOperationMapper.save(feeVo);
    }

    @Override
    public List<BmsLogOperationModel> findListForLog(Long id) {
        BmsLogisticsContractModel managementModel = mapper.findById(id, BmsLogisticsContractModel.class);
        if (ObjectUtil.isEmpty(managementModel)) {
            throw new PluginException("查询详情信息为空");
        }
        Criteria lCriteria = Criteria.forClass(BmsLogOperationModel.class);
        Restriction r1 = Restrictions.eq("orderNo", managementModel.getContractNo());
        Restriction r2 = Restrictions.eq("logType", 2);
        Restriction r3 = Restrictions.eq("enterpriseId", managementModel.getEnterpriseId());
        lCriteria.setRestriction(Restrictions.and(r1, r2, r3));
        return logOperationMapper.findByCriteria(lCriteria);
    }

    @Override
    public List<ContractLogQueryDTO> logQuery(ContractLogQueryVO vo) {
        UserEntity user = PlgFxUsrUtils.getUserEntity();
        Criteria criteria = Criteria.forClass(BmsLogOperationModel.class);
        Restriction r1 = Restrictions.eq(BmsLogOperationModel::getLogType, 2);
        Restriction r2 = Restrictions.eq(BmsLogOperationModel::getOrderNo, vo.getContractNo());
        Restriction r3 = Restrictions.eq(BmsLogOperationModel::getEnterpriseId, user.getEnterpriseId());
        criteria.setRestriction(Restrictions.and(r1, r2, r3));
        criteria.setOrder(Order.newInstance().desc("createtime"));
        List<BmsLogOperationModel> models = logOperationMapper.findByCriteria(criteria);

        List<ContractLogQueryDTO> dtos = Lists.newArrayList();
        for (BmsLogOperationModel model : models) {
            ContractLogQueryDTO dto = new ContractLogQueryDTO();
            BeanUtils.copyProperties(model, dto);
            dtos.add(dto);
        }
        return dtos;
    }
}