package com.izouma.dingdong.service;

import cn.hutool.core.util.ObjectUtil;
import com.izouma.dingdong.domain.OrderInfo;
import com.izouma.dingdong.domain.OrderRefundApply;
import com.izouma.dingdong.domain.SysConfig;
import com.izouma.dingdong.enums.*;
import com.izouma.dingdong.exception.BusinessException;
import com.izouma.dingdong.repo.OrderInfoRepo;
import com.izouma.dingdong.repo.OrderRefundApplyRepo;
import com.izouma.dingdong.repo.SysConfigRepo;
import com.izouma.dingdong.repo.UserRepo;
import com.izouma.dingdong.repo.merchant.MerchantRepo;
import com.izouma.dingdong.repo.rider.RiderRepo;
import com.izouma.dingdong.service.merchant.MerchantSettingsService;
import com.izouma.dingdong.service.rider.RiderService;
import com.izouma.dingdong.utils.SnowflakeIdWorker;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;


@Service
@Slf4j
public class OrderRefundApplyService {

    @Autowired
    private OrderRefundApplyRepo    orderRefundApplyRepo;
    @Autowired
    private OrderInfoRepo           orderInfoRepo;
    @Autowired
    private UserRepo                userRepo;
    @Autowired
    private MerchantRepo            merchantRepo;
    @Autowired
    private MerchantSettingsService merchantSettingsService;
    @Autowired
    private RiderService            riderService;
    @Autowired
    private SysConfigRepo           sysConfigRepo;

    private OrderStatus status;

    /**
     * 申请退款
     *
     * @param orderId 订单号
     * @param reason  退款缘由
     * @param remark  备注
     * @param img     图片
     */
    public OrderRefundApply apply(Long orderId, RefundReason reason, String remark, String img) {
        OrderInfo order = orderInfoRepo.findById(orderId).orElseThrow(new BusinessException("无记录"));

        OrderRefundApply apply = orderRefundApplyRepo.findByOrderId(orderId);
        if (apply != null) {
            if (RefundStatus.PENDING.equals(apply.getStatus())) {
                throw new BusinessException("申请中");
            } else {
                throw new BusinessException("已申请过");
            }
        }

        //记录原来的订单状态
        status = order.getStatus();
        switch (status) {
            case UNPAID:
                throw new BusinessException("暂未支付");
            case REFUNDED:
                throw new BusinessException("订单已退");
            case CANCELLED:
                throw new BusinessException("订单已取消");
            case REFUNDED_PENDING:
                throw new BusinessException("申请中");
        }

        order.setStatus(OrderStatus.REFUNDED_PENDING);
        order.setReason(reason);
        orderInfoRepo.save(order);

        return orderRefundApplyRepo.save(OrderRefundApply.builder()
                .status(RefundStatus.PENDING)
                .applyTime(LocalDateTime.now())
                .reason(reason)
                .img(img)
                .remark(remark)
                .orderId(orderId)
                .enabled(true)
                .report(false)
                .merchantId(order.getMerchantId())
                .build());
    }

    /**
     * 商家审核退款 线下退
     *
     * @param applyId       申请退款ID
     * @param merchantAgree 商家是否通过
     */
    public void audit(Long applyId, Boolean merchantAgree, Boolean payRider) {
        OrderRefundApply apply = orderRefundApplyRepo.findById(applyId).orElseThrow(new BusinessException("无记录"));
        if (apply.getStatus() != RefundStatus.PENDING) {
            return;
        }

        //OrderInfo orderInfo = apply.getOrderInfo();
        OrderInfo orderInfo = orderInfoRepo.findById(apply.getOrderId()).orElseThrow(new BusinessException("无订单"));

        userRepo.findById(orderInfo.getUserId()).orElseThrow(new BusinessException("无用户"));
        if (merchantAgree) {

            String refundId = String.valueOf(new SnowflakeIdWorker(1, 1).nextId());
            apply.setStatus(RefundStatus.PENDING_PAYMENT);
            apply.setMerchantAgree(true);

            //商家同意损失都由商家承担 完成订单商家才得到钱，所以无需减
            apply.setMerchantLiability(BigDecimal.ONE);
            apply.setRiderLiability(BigDecimal.ZERO);
            apply.setPlatformLiability(BigDecimal.ZERO);

            if (StringUtils.isEmpty(apply.getRefundId())) {
                apply.setRefundId(refundId);
            }

            //退款，线下退款订单完成商家才得款
            orderInfo.setStatus(OrderStatus.REFUNDING);

            //骑手得应得的
            if (payRider) {
                //运费
                BigDecimal deliveryAmount = orderInfo.getDeliveryAmount();
                //骑手收入
                Long merId = merchantRepo.findUserIdById(orderInfo.getMerchantId());
                riderService.income(orderInfo.getRiderId(), merId, deliveryAmount, FinancialType.INCOME, apply.getOrderId()
                        .toString());
                //商家支出
                //User riderUser = userRepo.findById(riderRepo.findUserIdById(orderInfo.getRiderId())).orElseThrow(new BusinessException("无用户"));
                Long riderUserId = orderInfo.getRiderId();
                merchantSettingsService.income(apply.getMerchantId(), riderUserId, deliveryAmount, FinancialType.LOSE_MONEY, apply
                        .getOrderId()
                        .toString());
            }

        } else {

            apply.setStatus(RefundStatus.PENDING);
            apply.setMerchantAgree(false);
            //申请退款中
            orderInfo.setStatus(OrderStatus.REFUNDED_PENDING);
            //apply.getOrderInfo().setStatus((status != null) ? status : OrderStatus.PAID);
            //上报到后台
            apply.setReport(true);
        }

        apply.setAuditTime(LocalDateTime.now());
        orderInfoRepo.save(orderInfo);
        orderRefundApplyRepo.save(apply);


    }

    /*
    取消退款
     */
    public void cancelRefundApply(Long orderId) {
        orderInfoRepo.findById(orderId).orElseThrow(new BusinessException("无订单"));
        OrderRefundApply apply = orderRefundApplyRepo.findByOrderIdAndStatus(orderId, RefundStatus.PENDING)
                .orElseThrow(new BusinessException("未申请退款"));
        apply.setStatus(RefundStatus.CANCEL);
        apply.getOrderInfo().setStatus((status != null) ? status : OrderStatus.PAID);
        orderInfoRepo.save(apply.getOrderInfo());
        orderRefundApplyRepo.save(apply);
    }

    /*
    商家的所有退款订单
     */
    public List<OrderRefundApply> merchantRefund(Long id) {
        return orderRefundApplyRepo.findAllByMerchantId(id);
    }


    //平台
    public void platformAudit(Long applyId, Boolean agree, BigDecimal merchantLiability, BigDecimal riderLiability, Boolean isCarryOut) {

        OrderRefundApply apply = orderRefundApplyRepo.findById(applyId).orElseThrow(new BusinessException("无记录"));
        if (ObjectUtil.isNull(merchantLiability)) {
            merchantLiability = BigDecimal.ZERO;
        }
        if (ObjectUtil.isNull(riderLiability)) {
            riderLiability = BigDecimal.ZERO;
        }

        OrderInfo orderInfo = orderInfoRepo.findById(apply.getOrderId()).orElseThrow(new BusinessException("无订单"));

        if (agree) {
            apply.setPlatformAgree(true);
            apply.setPlatformLiability(BigDecimal.ONE.subtract(riderLiability).subtract(merchantLiability));
            apply.setRiderLiability(riderLiability);
            apply.setMerchantLiability(merchantLiability);

            if (!isCarryOut) {
                //先收入钱
                this.orderCarryOut(apply.getOrderId());
            }

            if (!merchantLiability.equals(BigDecimal.ZERO)) {
                //商家所赔金额
                BigDecimal merAmount = orderInfo.getRealAmount().multiply(merchantLiability);
                merchantSettingsService.income(apply.getMerchantId(), orderInfo.getUserId(), merAmount, FinancialType.REFUND, apply
                        .getOrderId()
                        .toString());
            }

            if (!riderLiability.equals(BigDecimal.ZERO)) {
                //骑手赔付金额
                BigDecimal riderAmount = orderInfo.getRealAmount().multiply(riderLiability);
                riderService.income(orderInfo.getRiderId(), orderInfo.getUserId(), riderAmount, FinancialType.REFUND, apply
                        .getOrderId()
                        .toString());
            }

            //改状态
            orderInfo.setStatus(OrderStatus.REFUNDING);
            apply.setStatus(RefundStatus.PENDING_PAYMENT);
        } else {
            apply.setPlatformAgree(false);
            //原状态
            orderInfo.setStatus(OrderStatus.PAID);
            orderInfo.setCancel(false);
            //改状态
            apply.setStatus(RefundStatus.DENY);
        }

        orderInfoRepo.save(orderInfo);
        apply.setPlatformAuditTime(LocalDateTime.now());
        orderRefundApplyRepo.save(apply);
    }

    /*
    订单完成结算钱
    */
    public void orderCarryOut(Long orderId) {
        OrderInfo orderInfo = orderInfoRepo.findById(orderId).orElseThrow(new BusinessException("无订单"));

        //扣除金额
        SysConfig sysConfig = sysConfigRepo.findByName("commission").orElseThrow(new BusinessException("无设置"));

        //实付减运费
        BigDecimal subtractDelivery = orderInfo.getRealAmount().subtract(orderInfo.getDeliveryAmount());
        //平台抽成 (实付金额减运费)
        BigDecimal platform = subtractDelivery.multiply(new BigDecimal(sysConfig.getValue()));

        //商家应得 = 减去骑手应得，减去平台抽成
        BigDecimal deserve = subtractDelivery.subtract(platform);
        merchantSettingsService.income(orderInfo.getMerchantId(), orderInfo.getUserId(), deserve, FinancialType.INCOME, orderInfo
                .getId()
                .toString());

        //骑手应得
        riderService.income(orderInfo.getRiderId(), orderInfo.getUserId(), orderInfo.getDeliveryAmount(), FinancialType.INCOME, orderInfo
                .getId()
                .toString());
    }

    /*
    打款
     */
    public void payment(Long applyId) {
        OrderRefundApply apply = orderRefundApplyRepo.findById(applyId).orElseThrow(new BusinessException("无退款申请"));
        apply.setStatus(RefundStatus.SUCCESS);
        apply.setRefundTime(LocalDateTime.now());

        OrderInfo orderInfo = orderInfoRepo.findById(apply.getOrderId()).orElseThrow(new BusinessException("无订单"));
        orderInfo.setStatus(OrderStatus.REFUNDED);
        orderInfoRepo.save(orderInfo);
        orderRefundApplyRepo.save(apply);
    }
}
