
package com.tmerclub.cloud.order.controller.platform;


import cn.hutool.core.date.DateUtil;
import com.tmerclub.cloud.api.multishop.feign.ShopWalletFeignClient;
import com.tmerclub.cloud.api.order.constant.OrderStatus;
import com.tmerclub.cloud.api.payment.constant.PayEntry;
import com.tmerclub.cloud.api.payment.constant.PaySysType;
import com.tmerclub.cloud.api.payment.dto.PayInfoApiDto;
import com.tmerclub.cloud.api.payment.feign.PaymentFeignClient;
import com.tmerclub.cloud.api.vo.EsPageVO;
import com.tmerclub.cloud.common.constant.PayType;
import com.tmerclub.cloud.common.database.dto.PageDTO;
import com.tmerclub.cloud.common.exception.LuckException;
import com.tmerclub.cloud.common.leaf.manager.SegmentManager;
import com.tmerclub.cloud.common.order.constant.ReturnProcessStatusEnum;
import com.tmerclub.cloud.common.order.dto.OrderRefundSearchDTO;
import com.tmerclub.cloud.common.order.vo.EsOrderRefundVO;
import com.tmerclub.cloud.common.order.vo.OrderItemVO;
import com.tmerclub.cloud.common.response.ServerResponseEntity;
import com.tmerclub.cloud.common.security.AuthUserContext;
import com.tmerclub.cloud.common.util.BeanUtil;
import com.tmerclub.cloud.common.util.Json;
import com.tmerclub.cloud.common.util.PriceUtil;
import com.tmerclub.cloud.order.constant.*;
import com.tmerclub.cloud.order.constant.*;
import com.tmerclub.cloud.order.dto.OrderRefundInterventionDTO;
import com.tmerclub.cloud.order.model.Order;
import com.tmerclub.cloud.order.model.OrderItem;
import com.tmerclub.cloud.order.model.OrderRefundAddr;
import com.tmerclub.cloud.order.service.OrderItemService;
import com.tmerclub.cloud.order.service.OrderRefundAddrService;
import com.tmerclub.cloud.order.service.OrderRefundService;
import com.tmerclub.cloud.order.service.OrderService;
import com.tmerclub.cloud.order.vo.OrderRefundAddrVO;
import com.tmerclub.cloud.order.vo.OrderRefundVO;
import io.swagger.v3.oas.annotations.Operation;
import org.apache.dubbo.config.annotation.DubboReference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Objects;


/**
 * @author cl
 */
@RestController("platformOrderRefundController")
@RequestMapping("/p/order_refund")
public class OrderRefundController {

    private final Logger LOGGER = LoggerFactory.getLogger(OrderRefundController.class);
    @Autowired
    private OrderRefundService orderRefundService;
    @Autowired
    private OrderRefundAddrService orderRefundAddrService;
    @Autowired
    private OrderService orderService;
    @Autowired
    private OrderItemService orderItemService;
    @Autowired
    private ShopWalletFeignClient shopWalletFeignClient;
    @Autowired
    private SegmentManager segmentManager;
    @DubboReference
    private PaymentFeignClient paymentFeignClient;

    /**
     * 查看我的退款订单列表
     */
    @GetMapping("/page")
    @Operation(summary = "我的退款订单列表", description = "我的退款订单列表，显示数量时候")
    public ServerResponseEntity<EsPageVO<EsOrderRefundVO>> list(PageDTO page, OrderRefundSearchDTO orderRefundPageDTO) {
        orderRefundPageDTO.setSysType(AuthUserContext.get().getSysType());
        EsPageVO<EsOrderRefundVO> pageList = orderRefundService.page(page, orderRefundPageDTO);
        return ServerResponseEntity.success(pageList);
    }

    /**
     * 通过id查询
     *
     * @param refundId id
     * @return 查询详细信息
     */
    @GetMapping("/info/{refundId}")
    public ServerResponseEntity<OrderRefundVO> getById(@PathVariable("refundId") Long refundId) {
        OrderRefundVO orderRefund = orderRefundService.getDetailByRefundId(refundId);
        if (Objects.equals(orderRefund.getApplyType(), RefundApplyType.REFUND_AND_RETURNS.value()) && orderRefund.getHandelTime() != null) {
            LOGGER.info("退货退款，查询退货地址");
            OrderRefundAddr orderRefundAddr = orderRefundAddrService.getByRefundId(refundId);
            orderRefund.setOrderRefundAddr(BeanUtil.map(orderRefundAddr, OrderRefundAddrVO.class));
        }
        return ServerResponseEntity.success(orderRefund);
    }

    /**
     * 平台处理退款介入
     */
    @PutMapping("/handle_platform_intervention")
    @Operation(summary = "平台处理退款介入")
    public ServerResponseEntity<?> hanlePlatormIntervertion(@RequestBody OrderRefundInterventionDTO orderRefundParam) {
        OrderRefundVO orderRefundVO = orderRefundService.getByRefundId(orderRefundParam.getRefundId());
        if (Objects.isNull(orderRefundVO)) {
            // 撤销失败 退款订单不存在
            throw new LuckException("退款订单不存在");
        }
        if (Objects.equals(orderRefundVO.getReturnMoneySts(), ReturnProcessStatusEnum.SUCCESS.value())) {
            throw new LuckException("退款已经成功，不能处理介入请求");
        }
        if (!Objects.equals(orderRefundVO.getReturnMoneySts(), ReturnProcessStatusEnum.FAIL.value())) {
            throw new LuckException("订单退款状态异常");
        }
        if (!Objects.equals(orderRefundVO.getPlatformInterventionStatus(), PlatformInterventionStatus.APPLY.value())) {
            throw new LuckException("平台介入状态异常");
        }
        Boolean unStartCheck = DateUtil.compare(DateUtil.offsetDay(orderRefundVO.getApplyInterventionTime(),3) , DateUtil.date()) > 0;
        if (unStartCheck) {
            throw new LuckException("未到平台处理时间，不能处理本次介入");
        }
        Boolean outTimeCheck = DateUtil.compare(DateUtil.offsetDay(orderRefundVO.getApplyInterventionTime(),7) , DateUtil.date()) < 0;
        if (outTimeCheck) {
            throw new LuckException("已过平台介入时间，不能处理本次介入");
        }
        // 平台拒绝退款介入申请
        if (Objects.equals(orderRefundParam.getPlatformInterventionRefundType(), RefundStsType.DISAGREE.value())) {
            orderRefundVO.setPlatformInterventionStatus(PlatformInterventionStatus.REJECT.value());
            orderRefundService.disagreeIntervention(orderRefundParam, orderRefundVO);
            LOGGER.info("平台拒绝退款介入申请");
            return ServerResponseEntity.success();
        }
        Order order = orderService.getOrderByOrderIdAndUserId(orderRefundVO.getOrderId(), orderRefundVO.getUserId());
        if (orderRefundParam.getRefundAmount() > orderRefundVO.getRefundActualTotal()) {
            throw new LuckException("当前退款金额大于最大可退款金额");
        }
        Long freightAmount = order.getFreightAmount() - order.getPlatformFreeFreightAmount();
        if (Objects.equals(orderRefundVO.getRefundType(),1) && Objects.equals(order.getStatus(), OrderStatus.PAYED.value()) && orderRefundParam.getRefundAmount() < freightAmount) {
            throw new LuckException("待发货订单整单退款金额必须大于运费金额");
        }
        if(Objects.equals(orderRefundParam.getPlatformInterventionRefundType(), InterventionRefundType.COMMON.value())) {
            if (Objects.equals(order.getWaitPurchase(), 1)) {
                throw new LuckException("待采购订单不能选择商家供应商共同承担退款");
            }
            if (Objects.equals(orderRefundVO.getSupplierHandleStatus(), -1) && !Objects.equals(orderRefundVO.getSupplierId(),0L)) {
                throw new LuckException("代销订单商家自行处理的退款,不能选择商家供应商共同承担");
            }
        }
        // 如果是店铺独立承担，判断一下是供应商订单还是普通订单
        // 如果是供应商订单且不是待采购的订单，需要判断一下店铺的已结算的钱是否够
        boolean checkOrder = Objects.equals(orderRefundParam.getPlatformInterventionRefundType(), InterventionRefundType.SHOP.value()) && !Objects.equals(orderRefundVO.getSupplierId(), 0L);
        // 判断和计算一下金额
        Long supplierRealRefundAmount = calculateAmount(orderRefundParam,orderRefundVO,order,freightAmount);
        // 不是待采购状态的供应商订单，才检查下钱是否足够
        if (checkOrder && !Objects.equals(order.getWaitPurchase(), 1)) {
            // 检查一下商家结算金额是否足够
            ServerResponseEntity<Long> amountResp = shopWalletFeignClient.getSettlementAmountByShopId(orderRefundVO.getShopId(), order.getPaySysType());
            if (!amountResp.isSuccess()) {
                LOGGER.error("查询商家结算金额失败，失败原因：{}", amountResp.getMsg());
                throw new LuckException(amountResp.getMsg());
            }
            if (amountResp.getData() < supplierRealRefundAmount) {
                LOGGER.error("商家余额不足，商家结算金额：{}，供应商实际退款金额：{}", amountResp.getData(), supplierRealRefundAmount);
                return ServerResponseEntity.showFailMsg("商家余额不足，请去进行充值后重试");
            }
            // 如果订单是通联支付的，执行商家余额扣除，让商家跳转到通联输入支付密码等校验
            if (Objects.equals(order.getPaySysType(), PaySysType.ALLINPAY.value())) {
                LOGGER.info("订单是通联支付的，执行商家余额扣除，让商家跳转到通联输入支付密码等校验，退款单详情：{}", orderRefundVO);
                return allinPayBalancePay(supplierRealRefundAmount, order, order.getShopId(), orderRefundParam);
            }
        }
        orderRefundVO.setInterventionRefundType(orderRefundParam.getPlatformInterventionRefundType());
        orderRefundVO.setPlatformMessage(orderRefundParam.getPlatformMessage());
        orderRefundVO.setAfterInterventionRefundAmount(orderRefundVO.getRefundAmount());
        orderRefundVO.setRefundAmount(orderRefundParam.getRefundAmount());
        orderRefundService.agreeRefund(null,orderRefundVO);
        return ServerResponseEntity.success();
    }
    @GetMapping("/is_last_refund")
    @Operation(summary = "是否为最后一单退款")
    public ServerResponseEntity<Boolean> isLastRefund(Long refundId) {
        Long shopId = AuthUserContext.get().getTenantId();
        return ServerResponseEntity.success(orderRefundService.getIsLastRefund(refundId, shopId));
    }

    private Long calculateAmount(OrderRefundInterventionDTO orderRefundParam, OrderRefundVO orderRefundVO, Order order, Long freightAmount) {
        // 如果存在分销订单，则计算分销总金额
        List<OrderItem> orderItemList = orderItemService.listOrderItemsByOrderId(order.getOrderId());
        Long platformAmount = order.getPlatformAmount();
        Long platformCommission = order.getPlatformCommission();
        long purchaseAmount = orderItemList.stream().mapToLong(OrderItem::getItemPurchaseAmount).sum();
        long purchasePlatformCommission = orderItemList.stream().mapToLong(OrderItem::getPurchasePlatformCommission).sum();
        Long actualTotal = orderItemList.stream().mapToLong(OrderItem::getActualTotal).sum();
        long refundAmount = orderRefundParam.getRefundAmount();
        if(Objects.equals(orderRefundVO.getRefundType(), RefundType.SINGLE.value())){
            OrderItemVO orderItemVO = orderItemService.getByOrderItemId(orderRefundVO.getOrderItemId());
            platformAmount = orderItemVO.getPlatformShareReduce();
            platformCommission = orderItemVO.getPlatformCommission();
            purchaseAmount = orderItemVO.getItemPurchaseAmount();
            purchasePlatformCommission = orderItemVO.getPurchasePlatformCommission();
            actualTotal = orderItemVO.getActualTotal();
        }else if(Objects.equals(order.getStatus(),OrderStatus.PAYED.value())){
            // 待发货的订单还需要扣除运费进行计算
            refundAmount = refundAmount - freightAmount;
        }
        // 供应商改变金额 = 供应商改变金额 - 平台供应商佣金改变量 + 运费
        // 采购金额应退 = 采购金额 *（退款金额 / 实付金额）
        // 部分物品退款
        Long purchaseRefundAmount = PriceUtil.divideByBankerRounding(purchaseAmount * refundAmount, actualTotal);
        // 积分全部抵扣的情况下，退款金额为0，实付金额也为0，此时采购金额应退订单采购金额
        if (orderRefundVO.getRefundActualTotal() == 0 && refundAmount == 0) {
            purchaseRefundAmount = purchaseAmount;
        }
        // 计算平台退款金额（退款时将这部分钱退回给平台，所以商家要扣除从平台这里获取的金额）
        Long changePlatformAmount;
        // 平台佣金应退 = 平台佣金 *（退款金额 / 实付金额）
        Long changePlatformCommission;
        if (!Objects.equals(refundAmount ,orderRefundVO.getRefundActualTotal()) && refundAmount != 0) {
            // 平台退款金额 = 平台优惠金额 *（退款金额 / 实付金额）
            changePlatformAmount = PriceUtil.divideByBankerRounding(platformAmount * refundAmount, actualTotal);
            changePlatformCommission = PriceUtil.divideByBankerRounding(platformCommission * refundAmount, actualTotal);
        } else {
            changePlatformAmount = platformAmount;
            changePlatformCommission = platformCommission;
        }
        // 此处设置实际平台抵现金额
        orderRefundVO.setPlatformRefundAmount(changePlatformAmount);

        orderRefundVO.setPlatformRefundCommission(changePlatformCommission);
        // 平台供应商佣金应退 = 平台供应商佣金 *（退款金额 / 实付金额）
        // 退款金额为0时，是纯积分退款，金额无法修改，直接从商品中取佣金
        Long changeSupplierPlatformCommission;
        if (orderRefundVO.getRefundActualTotal() == 0 && refundAmount == 0L) {
            changeSupplierPlatformCommission = purchasePlatformCommission;
        } else {
            changeSupplierPlatformCommission = PriceUtil.divideByBankerRounding(purchasePlatformCommission * refundAmount, actualTotal);
        }
        orderRefundVO.setPurchaseRefundAmount(purchaseRefundAmount);
        orderRefundVO.setPurPlatformRefundCommission(changeSupplierPlatformCommission);
        return orderRefundVO.getPurchaseRefundAmount() - orderRefundVO.getPurPlatformRefundCommission()
                + order.getFreightAmount();
    }


    private ServerResponseEntity<?> allinPayBalancePay(Long payAmount, Order order, Long tenantId, OrderRefundInterventionDTO orderRefundDTO) {
        PayInfoApiDto orderPayInfoVO = new PayInfoApiDto();
        orderPayInfoVO.setBody("商家余额支付订单");
        orderPayInfoVO.setPayAmount(payAmount);
        orderPayInfoVO.setPayType(PayType.BALANCE.value());
        orderPayInfoVO.setOrderIds(order.getOrderId().toString());
        orderPayInfoVO.setRefundId(orderRefundDTO.getRefundId());
        orderPayInfoVO.setUserId(order.getUserId().toString());
        orderPayInfoVO.setReturnUrl(orderRefundDTO.getReturnUrl());
        orderPayInfoVO.setPayEntry(PayEntry.SHOP_BALANCE_PAY_REFUND_SPREAD.value());
        // 存入支付扩展信息
        orderRefundDTO.setSellerMsg(null);
        orderPayInfoVO.setExtendInfo(Json.toJsonString(orderRefundDTO));
        orderPayInfoVO.setBizUserId(order.getSupplierId().toString());
        orderPayInfoVO.setShopId(tenantId.toString());
        return paymentFeignClient.doAllinPayShopBalance(orderPayInfoVO);
    }
}
