package com.xxfc.platform.order.biz;


import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.github.wxiaoqi.security.common.biz.BaseBiz;
import com.github.wxiaoqi.security.common.exception.BaseException;
import com.github.wxiaoqi.security.common.util.process.ResultCode;
import com.github.wxiaoqi.security.common.vo.PageDataVO;
import com.xxfc.platform.order.contant.enumerate.CompanyWalletITypeEnum;
import com.xxfc.platform.order.contant.enumerate.CompanyWalletSourceEnum;
import com.xxfc.platform.order.contant.enumerate.DeductionTypeEnum;
import com.xxfc.platform.order.contant.enumerate.OrderStatusEnum;
import com.xxfc.platform.order.entity.*;
import com.xxfc.platform.order.mapper.CompanyWalletDetailMapper;
import com.xxfc.platform.order.pojo.account.OrderAccountDeduction;
import com.xxfc.platform.order.pojo.account.OrderAccountDetail;
import com.xxfc.platform.order.pojo.dto.CompanyWalletDetailDTO;
import com.xxfc.platform.order.pojo.dto.CompanyWalletDetailV2DTO;
import com.xxfc.platform.order.pojo.dto.WalletDetailDTO;
import com.xxfc.platform.order.pojo.vo.CompanyWalletDetailVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;

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


@Service
@Slf4j
public class CompanyWalletDetailV2Biz extends BaseBiz<CompanyWalletDetailMapper, CompanyWalletDetail>{


    @Autowired
    BaseOrderBiz orderBiz;

    @Autowired
    OrderRentVehicleBiz orderRentVehicleBiz;


    @Autowired
    OrderItemBiz orderItemBiz;

    @Autowired
    CompanyWalletBiz  companyWalletBiz;

    @Autowired
    OrderAccountBiz orderAccountBiz;






    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    //type1-完成;2-退款
    public void addOrUpd(CompanyWalletDetail companyWalletDetail,Integer type){
        String orderNo=companyWalletDetail.getCono();
        if (StringUtils.isBlank(orderNo)){
          throw  new BaseException("订单号不存在",ResultCode.FAILED_CODE);
        }
        log.info("---orderNo==="+orderNo);

        //获取订单相关信息
        BaseOrder baseOrder=new BaseOrder();
        baseOrder.setNo(orderNo);
        baseOrder=orderBiz.selectOne(baseOrder);
        if (baseOrder == null || baseOrder.getStatus()  < OrderStatusEnum.ORDER_FINISH.getCode() || StringUtils.isBlank(baseOrder.getRevenueJson())){
            throw  new BaseException("订单不存在或状态不是已完成",ResultCode.FAILED_CODE);
        }
        List<OrderRentVehicleDetail> orderRentVehicleDetails = orderRentVehicleBiz.listByOrderId(baseOrder.getId());
        if (orderRentVehicleDetails == null || orderRentVehicleDetails.size() == 0){
            throw  new BaseException("订单详情不存在",ResultCode.FAILED_CODE);
        }
        List<Integer> types=new ArrayList<>();
        if (type == 2 ){
            types.add(204);
        }else {
            types.add(201);
            types.add(202);
            types.add(203);
        }
        OrderAccountDetail accountDetail = getAccountDetail(types, baseOrder.getId());
        if (accountDetail == null ){
            throw  new BaseException("费用明细不存在",ResultCode.FAILED_CODE);
        }
        OrderItem orderItem=new OrderItem();
        orderItem.setOrderId(baseOrder.getId());
        List<OrderItem> orderItems = orderItemBiz.selectList(orderItem);
        BigDecimal damageSafeAmount = orderItems.stream().filter(x->x.getType()==102).map(OrderItem::getRealAmount).reduce(BigDecimal.ZERO, (x, y) -> x.add(y));
        OrderRentVehicleDetail vehicleDetail=orderRentVehicleDetails.get(0);

        //获取营收明细dto
        CompanyWalletDetailV2DTO walletDetailDTO=JSONUtil.toBean(baseOrder.getRevenueJson(), CompanyWalletDetailV2DTO.class);
        setDeductionDetail(accountDetail.getDeductions(),walletDetailDTO);
        walletDetailDTO.setDamageSafeAmount(damageSafeAmount);


        //获取门店钱包信息
        CompanyWallet endCompany=companyWalletBiz.selectById(vehicleDetail.getActualEndCompanyId());
        BigDecimal endCompanyAmount=BigDecimal.ZERO;
        if (endCompany != null){
            endCompanyAmount=endCompany.getBalance();
        }
        CompanyWallet vehicleCompany=companyWalletBiz.selectById(vehicleDetail.getVehicleCompanyId());
        BigDecimal vehicleCompanyAmount=BigDecimal.ZERO;
        if (vehicleCompany != null){
            vehicleCompanyAmount=vehicleCompany.getBalance();
        }
        CompanyWallet startCompany=companyWalletBiz.selectById(vehicleDetail.getStartCompanyId());
        BigDecimal startCompanyAmount=BigDecimal.ZERO;
        if (startCompany != null){
            startCompanyAmount=startCompany.getBalance();
        }
        CompanyWallet platformCompany=companyWalletBiz.selectById(walletDetailDTO.getPlatformCompanyId());
        BigDecimal platformCompanyAmount=BigDecimal.ZERO;
        if (platformCompany != null){
            platformCompanyAmount=platformCompany.getBalance();
        }

        //插入营收明细
        BigDecimal  closedVehicleAmout = BigDecimal.ZERO;//收车服务费
        BigDecimal  safeAmount = BigDecimal.ZERO;//不计免赔费
        BigDecimal  rentVehicleAmount = BigDecimal.ZERO;//车辆租赁费
        BigDecimal  orderComssion = BigDecimal.ZERO;//订单抽成
        BigDecimal  platformComssion= BigDecimal.ZERO;//平台抽成
        BigDecimal  lossSpecifiedAmount = BigDecimal.ZERO;//定损费
        BigDecimal  breakRulesRegulation= BigDecimal.ZERO;//违章费
        BigDecimal  violateAmount= BigDecimal.ZERO;//违约金
        if (walletDetailDTO.getIsCanelOrder() != null  && walletDetailDTO.getIsCanelOrder() == 1){
            violateAmount = walletDetailDTO.getViolateAmount();
            platformComssion=violateAmount.multiply(walletDetailDTO.getOrderExtract()).setScale(2, BigDecimal.ROUND_HALF_UP);
            violateAmount=violateAmount.subtract(platformComssion);
        }else {
            if (type == 2){
                breakRulesRegulation=walletDetailDTO.getBreakRulesRegulation();
            }else {
                closedVehicleAmout=walletDetailDTO.getClosedVehicleAmout() == null ? BigDecimal.ZERO : walletDetailDTO.getClosedVehicleAmout();
                safeAmount=walletDetailDTO.getDamageSafeAmount() == null ? BigDecimal.ZERO : walletDetailDTO.getDamageSafeAmount();
                safeAmount=safeAmount.add(walletDetailDTO.getDamageSafeAmount2() == null ? BigDecimal.ZERO : walletDetailDTO.getDamageSafeAmount2());
                orderComssion=walletDetailDTO.getOrderComssion();
                platformComssion=walletDetailDTO.getPlatformComssion();
                rentVehicleAmount=walletDetailDTO.getRentVehicleAmount();
                lossSpecifiedAmount=walletDetailDTO.getLossSpecifiedAmount();
                violateAmount=walletDetailDTO.getViolateAmount();
            }


        }
        if (closedVehicleAmout.compareTo(BigDecimal.ZERO)>0){
            endCompanyAmount=endCompanyAmount.add(closedVehicleAmout);
            companyWalletDetail.setAmount(closedVehicleAmout);
            companyWalletDetail.setCompanyId(vehicleDetail.getActualEndCompanyId());
            companyWalletDetail.setBranchId(vehicleDetail.getActualEndBranchId());
            companyWalletDetail.setSAmount(endCompanyAmount);
            companyWalletDetail.setSource(CompanyWalletSourceEnum.CLOSED_VEHICLE.getCode());
            companyWalletDetail.setItype(CompanyWalletITypeEnum.VEHICLE.getCode());
            companyWalletDetail.setId(null);
            insertSelective(companyWalletDetail);
        }if (safeAmount.compareTo(BigDecimal.ZERO)>0){
            BigDecimal amount=mapper.sumAmountByNo(orderNo,vehicleDetail.getVehicleCompanyId());
            vehicleCompanyAmount=vehicleCompanyAmount.add(safeAmount);
            companyWalletDetail.setAmount(safeAmount);
            companyWalletDetail.setCompanyId(vehicleDetail.getVehicleCompanyId());
            companyWalletDetail.setBranchId(vehicleDetail.getVehicleBranchId());
            companyWalletDetail.setSAmount(safeAmount.add(amount));
            companyWalletDetail.setSource(CompanyWalletSourceEnum.DAMAGE_SAFE.getCode());
            companyWalletDetail.setItype(CompanyWalletITypeEnum.VEHICLE.getCode());
            companyWalletDetail.setId(null);
            insertSelective(companyWalletDetail);
        }if (rentVehicleAmount.compareTo(BigDecimal.ZERO)>0){
            BigDecimal amount=mapper.sumAmountByNo(orderNo,vehicleDetail.getVehicleCompanyId());
            vehicleCompanyAmount=vehicleCompanyAmount.add(rentVehicleAmount);
            companyWalletDetail.setAmount(rentVehicleAmount);
            companyWalletDetail.setCompanyId(vehicleDetail.getVehicleCompanyId());
            companyWalletDetail.setBranchId(vehicleDetail.getVehicleBranchId());
            companyWalletDetail.setSAmount(rentVehicleAmount.add(amount));
            companyWalletDetail.setSource(CompanyWalletSourceEnum.RENT_VEHICLE.getCode());
            companyWalletDetail.setItype(CompanyWalletITypeEnum.VEHICLE.getCode());
            companyWalletDetail.setId(null);
            insertSelective(companyWalletDetail);
        }if (orderComssion.compareTo(BigDecimal.ZERO)>0){
            BigDecimal amount=mapper.sumAmountByNo(orderNo,vehicleDetail.getStartCompanyId());
            startCompanyAmount=startCompanyAmount.add(orderComssion);
            companyWalletDetail.setAmount(orderComssion);
            companyWalletDetail.setCompanyId(vehicleDetail.getStartCompanyId());
            companyWalletDetail.setBranchId(vehicleDetail.getStartBranchId());
            companyWalletDetail.setSAmount(orderComssion.add(amount));
            companyWalletDetail.setSource(CompanyWalletSourceEnum.ORDER_COMSSION.getCode());
            companyWalletDetail.setItype(CompanyWalletITypeEnum.VEHICLE.getCode());
            companyWalletDetail.setId(null);
            insertSelective(companyWalletDetail);
        }if (platformComssion.compareTo(BigDecimal.ZERO)>0){
            BigDecimal amount=mapper.sumAmountByNo(orderNo,walletDetailDTO.getPlatformCompanyId());
            platformCompanyAmount=platformCompanyAmount.add(platformComssion);
            companyWalletDetail.setAmount(platformComssion);
            companyWalletDetail.setCompanyId(walletDetailDTO.getPlatformCompanyId());
            companyWalletDetail.setBranchId(walletDetailDTO.getPlatformBranchId());
            companyWalletDetail.setSAmount(platformComssion.add(amount));
            companyWalletDetail.setSource(CompanyWalletSourceEnum.PLATFORM_COMSSION.getCode());
            companyWalletDetail.setItype(CompanyWalletITypeEnum.PLATFORM.getCode());
            companyWalletDetail.setId(null);
            insertSelective(companyWalletDetail);
        }if (lossSpecifiedAmount.compareTo(BigDecimal.ZERO)>0){
            BigDecimal amount=mapper.sumAmountByNo(orderNo,vehicleDetail.getVehicleCompanyId());
            vehicleCompanyAmount=vehicleCompanyAmount.add(lossSpecifiedAmount);
            companyWalletDetail.setAmount(lossSpecifiedAmount);
            companyWalletDetail.setCompanyId(vehicleDetail.getVehicleCompanyId());
            companyWalletDetail.setBranchId(vehicleDetail.getVehicleBranchId());
            companyWalletDetail.setSAmount(lossSpecifiedAmount.add(amount));
            companyWalletDetail.setSource(CompanyWalletSourceEnum.LOSS_SPECIFIED.getCode());
            companyWalletDetail.setItype(CompanyWalletITypeEnum.LOSS.getCode());
            companyWalletDetail.setId(null);
            insertSelective(companyWalletDetail);
        }if (breakRulesRegulation.compareTo(BigDecimal.ZERO)>0){
            BigDecimal amount=mapper.sumAmountByNo(orderNo,vehicleDetail.getVehicleCompanyId());
            vehicleCompanyAmount=vehicleCompanyAmount.add(breakRulesRegulation);
            companyWalletDetail.setAmount(breakRulesRegulation);
            companyWalletDetail.setCompanyId(vehicleDetail.getVehicleCompanyId());
            companyWalletDetail.setBranchId(vehicleDetail.getVehicleBranchId());
            companyWalletDetail.setSAmount(breakRulesRegulation.add(amount));
            companyWalletDetail.setSource(CompanyWalletSourceEnum.BREAK_RULES_REGULATION.getCode());
            companyWalletDetail.setItype(CompanyWalletITypeEnum.REGULATION.getCode());
            companyWalletDetail.setId(null);
            insertSelective(companyWalletDetail);
        }if (violateAmount.compareTo(BigDecimal.ZERO)>0){
            BigDecimal amount=mapper.sumAmountByNo(orderNo,vehicleDetail.getVehicleCompanyId());
            vehicleCompanyAmount=vehicleCompanyAmount.add(violateAmount);
            companyWalletDetail.setAmount(violateAmount);
            companyWalletDetail.setCompanyId(vehicleDetail.getVehicleCompanyId());
            companyWalletDetail.setBranchId(vehicleDetail.getVehicleBranchId());
            companyWalletDetail.setSAmount(violateAmount.add(amount));
            companyWalletDetail.setSource(CompanyWalletSourceEnum.VIOLATE_AMOUNT.getCode());
            companyWalletDetail.setItype(CompanyWalletITypeEnum.VIOLATE.getCode());
            companyWalletDetail.setId(null);
            insertSelective(companyWalletDetail);
        }

        //更新钱包
        Long time=System.currentTimeMillis();
       if (endCompany == null ){
           endCompany=new CompanyWallet();
           endCompany.setCompanyId(vehicleDetail.getActualEndCompanyId());
           endCompany.setBalance(endCompanyAmount);
           endCompany.setLastIntime(time);
           endCompany.setTotalAmount(endCompanyAmount);
           companyWalletBiz.insertSelective(endCompany);
       }else {
           endCompany.setTotalAmount(endCompany.getTotalAmount().add(endCompanyAmount));
           endCompany.setBalance(endCompany.getBalance().add(endCompanyAmount));
           endCompany.setLastIntime(time);
           companyWalletBiz.updCompanyWallet(endCompany);
       }
        vehicleCompany=companyWalletBiz.selectById(vehicleDetail.getVehicleCompanyId());
        if (vehicleCompany == null ){
            vehicleCompany=new CompanyWallet();
            vehicleCompany.setCompanyId(vehicleDetail.getVehicleCompanyId());
            vehicleCompany.setBalance(vehicleCompanyAmount);
            vehicleCompany.setLastIntime(time);
            vehicleCompany.setTotalAmount(vehicleCompanyAmount);
            companyWalletBiz.insertSelective(vehicleCompany);
        }else {
            vehicleCompany.setTotalAmount(vehicleCompany.getTotalAmount().add(vehicleCompanyAmount));
            vehicleCompany.setBalance(vehicleCompany.getBalance().add(vehicleCompanyAmount));
            vehicleCompany.setLastIntime(time);
            companyWalletBiz.updCompanyWallet(vehicleCompany);
        }
        startCompany=companyWalletBiz.selectById(vehicleDetail.getStartCompanyId());
        if (startCompany == null ){
            startCompany=new CompanyWallet();
            startCompany.setCompanyId(vehicleDetail.getStartCompanyId());
            startCompany.setBalance(startCompanyAmount);
            startCompany.setLastIntime(time);
            startCompany.setTotalAmount(startCompanyAmount);
            companyWalletBiz.insertSelective(startCompany);
        }else {
            startCompany.setTotalAmount(startCompany.getTotalAmount().add(startCompanyAmount));
            startCompany.setBalance(startCompany.getBalance().add(startCompanyAmount));
            startCompany.setLastIntime(time);
            companyWalletBiz.updCompanyWallet(startCompany);
        }
        platformCompany=companyWalletBiz.selectById(walletDetailDTO.getPlatformCompanyId());
        if (platformCompany == null ){
            platformCompany=new CompanyWallet();
            platformCompany.setCompanyId(walletDetailDTO.getPlatformCompanyId());
            platformCompany.setBalance(platformCompanyAmount);
            platformCompany.setLastIntime(time);
            platformCompany.setTotalAmount(platformCompanyAmount);
            companyWalletBiz.insertSelective(platformCompany);
        }else {
            platformCompany.setTotalAmount(platformCompany.getTotalAmount().add(platformCompanyAmount));
            platformCompany.setBalance(platformCompany.getBalance().add(platformCompanyAmount));
            platformCompany.setLastIntime(time);
            companyWalletBiz.updCompanyWallet(platformCompany);
        }
    }


    public PageDataVO<CompanyWalletDetailVo> selectList(WalletDetailDTO walletDetailDTO) {
        return PageDataVO.pageInfo(walletDetailDTO.getPage(), walletDetailDTO.getLimit(), () -> getList(walletDetailDTO));
    }

    public List<CompanyWalletDetailVo> getList(WalletDetailDTO walletDetailDTO){
        return  mapper.selectList(walletDetailDTO);
    }

    public JSONObject  getSumAmount(WalletDetailDTO walletDetailDTO){
        List<Integer> itypes=new ArrayList<>();
        itypes.add(1);
        walletDetailDTO.setItypes(itypes);
        BigDecimal amount = mapper.sumAmount(walletDetailDTO);
        JSONObject jsonObject=new JSONObject();
        jsonObject.put("orderAmount",amount);
        itypes=new ArrayList<>();
        itypes.add(2);
        itypes.add(3);
        itypes.add(4);
        walletDetailDTO.setItypes(itypes);
        amount = mapper.sumAmount(walletDetailDTO);
        jsonObject.put("otherAmount",amount);
        CompanyWallet companyWallet=companyWalletBiz.sumAmount(walletDetailDTO);
        if (companyWallet != null ){
            jsonObject.put("balance",companyWallet.getBalance());
            jsonObject.put("withdrawals",companyWallet.getWithdrawals());
        }

        return jsonObject;
    }



        public OrderAccountDetail getAccountDetail(List<Integer> types,Integer orderId) {
            Example example = new Example(OrderAccount.class);
            example.createCriteria().andEqualTo("orderId", orderId).andIn("accountType", types);
            List<OrderAccount> orderAccounts = orderAccountBiz.selectByExample(example);
            if (orderAccounts.size() > 0){
                OrderAccount orderAccount = orderAccounts.get(0);
                return  org.springframework.util.StringUtils.hasText(orderAccount.getAccountDetail()) ? JSON.parseObject(orderAccount.getAccountDetail(), OrderAccountDetail.class) : null;
            }

            return null;
    }


    public  void  setDeductionDetail(List<OrderAccountDeduction> deductions, CompanyWalletDetailV2DTO walletDetailV2DTO){
        for (OrderAccountDeduction orderAccountDeduction:deductions){
             Integer type=orderAccountDeduction.getType() == null ? 0 : orderAccountDeduction.getType();
             BigDecimal amount=orderAccountDeduction.getAmount() == null ?BigDecimal.ZERO : orderAccountDeduction.getAmount();
             if (Objects.equals(DeductionTypeEnum.VIOLATE_CANCEL.getCode(),type)){
                 walletDetailV2DTO.setIsCanelOrder(1);
                 walletDetailV2DTO.setViolateAmount(amount);
             }else {
                 walletDetailV2DTO.setIsCanelOrder(0);
                 if (Objects.equals(DeductionTypeEnum.VIOLATE_ADVANCE.getCode(),type) || Objects.equals(DeductionTypeEnum.VIOLATE_DELAY.getCode(),type)){
                     walletDetailV2DTO.setViolateAmount(amount);
                 }else if (Objects.equals(DeductionTypeEnum.VIOLATE_CHANGE_C.getCode(),type)){
                     walletDetailV2DTO.setChageAmount(amount);
                 }else if (Objects.equals(DeductionTypeEnum.CONSUME.getCode(),type)){
                     walletDetailV2DTO.setOrderAmount(amount);
                 }else if (Objects.equals(DeductionTypeEnum.DAMAGES.getCode(),type)){
                     walletDetailV2DTO.setLossSpecifiedAmount(amount);
                 }else if (Objects.equals(DeductionTypeEnum.VIOLATE_TRAFFIC_DEDUCT.getCode(),type)){
                     walletDetailV2DTO.setBreakRulesRegulation(amount);
                 }else if (Objects.equals(DeductionTypeEnum.OTHER_DELAY_SAFE.getCode(),type)){
                     walletDetailV2DTO.setDamageSafeAmount2(amount);
                 }
             }
        }

    }




}
