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

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.google.common.collect.Lists;
import com.prolog.framework.common.message.RestMessage;
import com.prolog.framework.core.restriction.Criteria;
import com.prolog.framework.core.restriction.Restriction;
import com.prolog.framework.core.restriction.Restrictions;
import com.prolog.product.core.framework.entity.UserEntity;
import com.prolog.rdc.tms.constant.BmsConstant;
import com.prolog.rdc.tms.dao.mapper.BmsBillPayFeeDetailMapper;
import com.prolog.rdc.tms.dao.mapper.ExpenseAccountMapper;
import com.prolog.rdc.tms.dao.mapper.ExpenseManagementMapper;
import com.prolog.rdc.tms.dao.mapper.ShipBillFeeTemporaryDetailMapper;
import com.prolog.rdc.tms.model.dto.ShipBillPriceDTO;
import com.prolog.rdc.tms.model.dto.SySParameterDTO;
import com.prolog.rdc.tms.model.entity.*;
import com.prolog.rdc.tms.rmi.feign.MaindataFeign;
import com.prolog.rdc.tms.service.strategy.AbstractSplitStrategyRuleHandler;
import com.prolog.rdc.tms.service.strategy.CostStrategyRuleHandler;
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.Component;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.List;
import java.util.Objects;

@Component
@CostStrategyRuleHandler(BmsConstant.PRICE)
public class PriceStrategy extends AbstractSplitStrategyRuleHandler {

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

    @Autowired
    private MaindataFeign maindataTmsResource;
    @Autowired
    private BmsBillPayFeeDetailMapper bmsBillPayFeeDetailMapper;
    @Autowired
    private ShipBillFeeTemporaryDetailMapper temporaryDetailMapper;
    @Autowired
    private ExpenseManagementMapper managementMapper;
    @Autowired
    private ExpenseAccountMapper expenseAccountMapper;

    /**
     * 一口价
     *
     * @param priceModel   计费数据
     * @param costStrategy 运单信息
     */
    @Override
    public List<ShipBillPriceDTO> executeStrategy(BmsLogisticsContractModel contractModel, BmsFreightPriceModel priceModel, BmsShipBillHeaderModel costStrategy,String source,UserEntity user) {
        logger.info("执行一口价计费....");
        List<ShipBillPriceDTO> list = Lists.newArrayList();
        ShipBillPriceDTO dto = new ShipBillPriceDTO();
        BigDecimal price = priceModel.getPrice();
        dto.setPrice(price);
        dto.setShipbillNo(costStrategy.getShipbillNo());
        dto.setCostContract(contractModel.getContractName());
        dto.setCostPriceTable(priceModel.getPriceName());
        dto.setFirstPartyId(contractModel.getFirstPartyId());
        dto.setFirstPartyCode(contractModel.getFirstPartyCode());
        dto.setFirstPartyName(contractModel.getFirstPartyName());

        this.saveFee(dto,costStrategy,contractModel,priceModel,user,price,source);
        list.add(dto);
        return list;
    }

    private void saveFee(ShipBillPriceDTO dto,BmsShipBillHeaderModel costStrategy, BmsLogisticsContractModel contractModel, BmsFreightPriceModel priceModel, UserEntity user,BigDecimal totPrice,String source) {
        // 新增费用信息
        BmsBillPayFeeDetailModel feeDetailModel = new BmsBillPayFeeDetailModel();
        RestMessage<String> expenseNo = maindataTmsResource.getCodeNumberByCode(BmsConstant.SHIP_BILL_EXPENSE_NO, "L");
        if (!expenseNo.isSuccess() || ObjectUtil.isEmpty(expenseNo)) {
            throw new PluginException("获取费用单号为空");
        }
        feeDetailModel.setExpenseNo(expenseNo.getData());
        feeDetailModel.setBillNo(costStrategy.getShipbillNo());
        feeDetailModel.setBillId(costStrategy.getId());
        feeDetailModel.setPayFeeType(1);
        feeDetailModel.setExpenseTypeName("运费");
        feeDetailModel.setTaxPoint(contractModel.getTaxPoint());
        feeDetailModel.setBillingSource(1);
        feeDetailModel.setBillingStatus(1);
        feeDetailModel.setBillingDate(DateUtil.date());
        feeDetailModel.setBillingContract(contractModel.getContractName());
        feeDetailModel.setBillingPrice(priceModel.getPriceName());
        //  费用编码、费用名称、费用科目名称、费用科目编码、费用类型 为价格表的费用反写（只有附加费才有）
        String expenseName = priceModel.getExpenseName();
        Criteria forClass = Criteria.forClass(BmsExpenseManagementModel.class);
        Restriction r7 = Restrictions.eq("status", 1);
        Restriction r8 = Restrictions.eq("expenseName", expenseName);
        Restriction r9 = Restrictions.eq("enterpriseId", user.getEnterpriseId());
        forClass.setRestriction(Restrictions.and(r7, r8,r9));
        List<BmsExpenseManagementModel> managementModels = managementMapper.findByCriteria(forClass);
        if (ObjectUtil.isEmpty(managementModels)) {
            throw new PluginException("获取费用信息失败");
        }
        BmsExpenseManagementModel managementModel = managementModels.get(0);
        feeDetailModel.setExpenseCode(managementModel.getExpenseCode());
        feeDetailModel.setExpenseName(managementModel.getExpenseName());
        feeDetailModel.setExpenseAccountCode(managementModel.getExpenseAccountCode());
        feeDetailModel.setExpenseAccountName(managementModel.getExpenseAccountName());
        // 支出，收入
        String expenseAccountCode = managementModel.getExpenseAccountCode();
        Criteria aClass = Criteria.forClass(ExpenseAccountModel.class);
        Restriction r11 = Restrictions.eq("expenseCode", expenseAccountCode);
        Restriction r12 = Restrictions.eq("status", 1);
        aClass.setRestriction(Restrictions.and(r11, r12));
        List<ExpenseAccountModel> mapper = expenseAccountMapper.findByCriteria(aClass);
        if (ObjectUtil.isNotEmpty(mapper)) {
            feeDetailModel.setExpenseType(mapper.get(0).getExpenseClassify());
            feeDetailModel.setExpenseTypeName(Objects.equals(mapper.get(0).getExpenseClassify(), 1) ? "收入" : "支出");
        }
        RestMessage<SySParameterDTO> parameterModel = maindataTmsResource.queryParameter();
        int taxPoint = Integer.parseInt(contractModel.getTaxPoint());
        if (ObjectUtil.isNotEmpty(parameterModel) && parameterModel.isSuccess()) {
            // 1：含税，2：未税
            Integer isTax = parameterModel.getData().getIsTax();
            // 含税金额 = 未税金额（1 + 税点）
            BigDecimal point = BigDecimal.valueOf(taxPoint).divide(BigDecimal.valueOf(100), 5, RoundingMode.HALF_UP).add(BigDecimal.valueOf(1));
            Integer costPrecision = parameterModel.getData().getCostPrecision();
            Integer costInteger = parameterModel.getData().getCostInteger();
            if (isTax == 1) {
                // 四舍五入
                if (costInteger == 1) {
                    totPrice = totPrice.divide(BigDecimal.valueOf(1),costPrecision,RoundingMode.HALF_UP);
                    feeDetailModel.setNoTaxAmt(totPrice.divide(point,costPrecision, RoundingMode.HALF_UP));
                }
                // 向上取整
                if (costInteger == 2) {
                    totPrice = totPrice.divide(BigDecimal.valueOf(1),costPrecision,RoundingMode.UP);
                    feeDetailModel.setNoTaxAmt(totPrice.divide(point,costPrecision, RoundingMode.UP));
                }
                // 向下取整
                if (costInteger == 3) {
                    totPrice = totPrice.divide(BigDecimal.valueOf(1),costPrecision,RoundingMode.DOWN);
                    feeDetailModel.setNoTaxAmt(totPrice.divide(point,costPrecision, RoundingMode.DOWN));
                }
                feeDetailModel.setTaxAmt(totPrice);
                feeDetailModel.setTax(totPrice.subtract(feeDetailModel.getNoTaxAmt()));
            } else {
                // 四舍五入
                if (costInteger == 1) {
                    totPrice = totPrice.divide(BigDecimal.valueOf(1),costPrecision,RoundingMode.HALF_UP);
                    feeDetailModel.setNoTaxAmt(totPrice);
                    feeDetailModel.setTaxAmt(totPrice.multiply(point).divide(BigDecimal.valueOf(1),costPrecision, RoundingMode.HALF_UP));
                    feeDetailModel.setTax(totPrice.multiply(point).divide(BigDecimal.valueOf(1),costPrecision, RoundingMode.HALF_UP).subtract(totPrice));

                }
                // 向上取整
                if (costInteger == 2) {
                    totPrice = totPrice.divide(BigDecimal.valueOf(1),costPrecision,RoundingMode.UP);
                    feeDetailModel.setNoTaxAmt(totPrice);
                    feeDetailModel.setTaxAmt(totPrice.multiply(point).divide(BigDecimal.valueOf(1),costPrecision, RoundingMode.UP));
                    feeDetailModel.setTax(totPrice.multiply(point).divide(BigDecimal.valueOf(1),costPrecision, RoundingMode.UP).subtract(totPrice));

                }
                // 向下取整
                if (costInteger == 3) {
                    totPrice = totPrice.divide(BigDecimal.valueOf(1),costPrecision,RoundingMode.DOWN);
                    feeDetailModel.setNoTaxAmt(totPrice);
                    feeDetailModel.setTaxAmt(totPrice.multiply(point).divide(BigDecimal.valueOf(1),costPrecision, RoundingMode.DOWN));
                    feeDetailModel.setTax(totPrice.multiply(point).divide(BigDecimal.valueOf(1),costPrecision, RoundingMode.DOWN).subtract(totPrice));
                }

            }
        }  else {
            feeDetailModel.setNoTaxAmt(BigDecimal.valueOf(0));
            feeDetailModel.setTaxAmt(totPrice);
            feeDetailModel.setTax(BigDecimal.valueOf(0));
        }
        feeDetailModel.setBillingType("");
        feeDetailModel.setCreateperson(user.getNickname());
        feeDetailModel.setCreatetime(DateUtil.date());
        feeDetailModel.setUpdateperson(user.getNickname());
        feeDetailModel.setUpdatetime(DateUtil.date());
        feeDetailModel.setEnterpriseId(user.getEnterpriseId());
        feeDetailModel.setEnterpriseName(user.getEnterpriseName());
        feeDetailModel.setExpenseStatus(2);
        feeDetailModel.setCheckStatus(0);
        // 0：试验，1：非试验
        if (source.equals("0")) {

            BmsShipBillFeeTemporaryDetailModel temporaryDetailModel = new BmsShipBillFeeTemporaryDetailModel();
            BeanUtils.copyProperties(feeDetailModel,temporaryDetailModel);
            temporaryDetailMapper.save(temporaryDetailModel);
        }else {

            // 类型为支出的含税金额
            // 通过费用科目编码 查询是否是支出的
//            String expenseAccountCode = managementModel.getExpenseAccountCode();
//            Criteria aClass = Criteria.forClass(ExpenseAccountModel.class);
//            Restriction r11 = Restrictions.eq("expenseCode", expenseAccountCode);
//            Restriction r12 = Restrictions.eq("status", 1);
//            aClass.setRestriction(Restrictions.and(r11,r12));
//            List<ExpenseAccountModel> mapper = expenseAccountMapper.findByCriteria(aClass);
//            if (ObjectUtil.isEmpty(mapper)) {
//                throw new PluginException("查询费用科目信息失败");
//            }
//            ExpenseAccountModel expenseAccountModel = mapper.get(0);
//            int expenseClassify = expenseAccountModel.getExpenseClassify();
//            if (expenseClassify == 2) {
//                dto.setPayAmount(dto.getPayAmount().add(feeDetailModel.getTaxAmt()));
//            }
//            // 类型为支出来源是价格表生成 含税金额
//            if (expenseClassify == 2 && feeDetailModel.getBillingSource().equals(1)) {
//                dto.setContractPayAmount(dto.getContractPayAmount().add(feeDetailModel.getTaxAmt()));
//            }

            bmsBillPayFeeDetailMapper.save(feeDetailModel);
        }
    }

}