package com.xxfc.platform.order.biz;

import cn.hutool.core.util.StrUtil;
import com.github.wxiaoqi.security.admin.dto.UserMemberDTO;
import com.github.wxiaoqi.security.admin.feign.UserFeign;
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.xxfc.platform.order.contant.enumerate.OrderStatusEnum;
import com.xxfc.platform.order.contant.enumerate.OrderTypeEnum;
import com.xxfc.platform.order.contant.enumerate.RefundTypeEnum;
import com.xxfc.platform.order.entity.*;
import com.xxfc.platform.order.mapper.BaseOrderMapper;
import com.xxfc.platform.order.pojo.order.OrderPageVO;
import com.xxfc.platform.tour.feign.TourFeign;
import com.xxfc.platform.universal.feign.ThirdFeign;
import com.xxfc.platform.universal.vo.OrderRefundVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import static com.github.wxiaoqi.security.common.constant.CommonConstants.SYS_FALSE;
import static com.github.wxiaoqi.security.common.constant.CommonConstants.SYS_TRUE;

/**
 * 
 *
 * @author zjw
 * @email nishijjo@qq.com
 * @date 2019-05-15 21:30:33
 */
@Service
@Slf4j
public class BaseOrderBiz extends BaseBiz<BaseOrderMapper,BaseOrder> {

    @Autowired
    OrderMemberDetailBiz orderMemberDetailBiz;

    @Autowired
    OrderTourDetailBiz orderTourDetailBiz;

    @Autowired
    OrderRentVehicleBiz orderRentVehicleBiz;

    @Autowired
    OrderRefundBiz orderRefundBiz;

    @Autowired
    ThirdFeign thirdFeign;

    @Autowired
    TourFeign tourFeign;

    @Autowired
    UserFeign userFeign;

    public List<OrderPageVO> pageByParm(Map<String, Object> paramMap){
        return mapper.pageByParm(paramMap);
    }
    public List<OrderPageVO> listOrder(Map<String, Object> paramMap){
        return mapper.listOrder(paramMap);
    }
    public List<OrderPageVO> getRentVehicle (Map<String, Object> paramMap) {
        return mapper.getRentVehicle(paramMap);
    }
    private static Map<Integer, List<Integer>> cancelAble;
    static {
        cancelAble = new HashMap<Integer, List<Integer>>();
        cancelAble.put(OrderTypeEnum.RentVehicle.getCode(), new LinkedList<Integer>(){{
            add(OrderStatusEnum.ORDER_UNPAY.getCode());
            add(OrderStatusEnum.ORDER_TOSTART.getCode());
        }});
        cancelAble.put(OrderTypeEnum.TOUR.getCode(), new LinkedList<Integer>(){{
            add(OrderStatusEnum.ORDER_UNPAY.getCode());
            add(OrderStatusEnum.ORDER_TOSTART.getCode());
        }});
        cancelAble.put(OrderTypeEnum.MEMBER.getCode(), new LinkedList<Integer>(){{
            add(OrderStatusEnum.ORDER_UNPAY.getCode());
        }});
    }

    /**
     * 取消订单
     * @param baseOrder
     */
    public void cancel(BaseOrder baseOrder) {
        if(cancelAble.get(baseOrder.getType()).contains(baseOrder.getStatus())) {
            int updateResult = this.updateSelectiveByIdRe(new BaseOrder(){{
                setId(baseOrder.getId());
                setStatus(OrderStatusEnum.ORDER_CANCEL.getCode());
                setCancelReason(baseOrder.getCancelReason());
                setVersion(baseOrder.getVersion());
            }});

            //如果取消失败，则抛异常
            if(updateResult <= 0) {
                throw new BaseException(ResultCode.DB_OPERATION_FAIL_CODE);
            }

            //触发退款流程
                //判断是否已支付
            if(baseOrder.getHasPay().equals(SYS_TRUE)) {
                //判断订单类型
                if(OrderTypeEnum.RentVehicle.getCode().equals(baseOrder.getType())) {
                    OrderRentVehicleDetail orvd = orderRentVehicleBiz.selectOne(new OrderRentVehicleDetail(){{
                        setOrderId(baseOrder.getId());
                    }});

                    //退款流程
                    refundProcess(baseOrder, orvd);

                }else if (OrderTypeEnum.TOUR.getCode().equals(baseOrder.getType())) {

                }
            }

            //处理取消流程
            if(OrderTypeEnum.RentVehicle.getCode().equals(baseOrder.getType())) {
                OrderRentVehicleDetail orvd = orderRentVehicleBiz.selectOne(new OrderRentVehicleDetail(){{
                    setOrderId(baseOrder.getId());
                }});
                //取消租车预定

                //取消租车免费天数使用
                if(null != orvd.getFreeDays() && orvd.getFreeDays() > 0) {
                    int result = userFeign.memberDays(baseOrder.getUserId(), orvd.getFreeDays(), UserFeign.MEMBER_DAYS_WITHDRAW);
                    if(result < 0) {
                        throw new BaseException(ResultCode.FAILED_CODE);
                    }
                }
                
            }else if(OrderTypeEnum.TOUR.getCode().equals(baseOrder.getType())) {
                OrderTourDetail otd = orderTourDetailBiz.selectOne(new OrderTourDetail(){{
                    setOrderId(baseOrder.getId());
                }});

                //增加库存
                tourFeign.stock(otd.getSpePriceId(), otd.getTotalNumber(), TourFeign.STOCK_PLUS);
            }
        }else {
            throw new BaseException(ResultCode.FAILED_CODE);
        }
    }

    private void refundProcess(BaseOrder baseOrder, OrderRentVehicleDetail orvd) {
        //计算退款金额
        // 1、押金 + 租金(规则扣除)
        BigDecimal refundAmont = orvd.getDeposit().add(baseOrder.getGoodsAmount());
        String refundTradeNo = thirdFeign.refund(new OrderRefundVo(){{
            setAmount(baseOrder.getRealAmount().multiply(new BigDecimal("100")).intValue());
            setRefundAmount(refundAmont.multiply(new BigDecimal("100")).intValue());
            setOrderNo(baseOrder.getNo());
            setRefundDesc("取消订单退款:"+ refundAmont.toString());
        }}).getData();

        //如果返回的流水为空，则当做失败
        Integer refundStatus = SYS_TRUE;
        if(StrUtil.isBlank(refundTradeNo)) {
            refundStatus = SYS_FALSE;
        }

        //创建订单退款记录
        OrderRefund orderRefund = new OrderRefund(){{
            setOrderId(baseOrder.getId());
            setRefundAmount(refundAmont);
            setRefundTime(System.currentTimeMillis());
            setRefundDesc("取消订单退款:"+ refundAmont.toString());
            setTradeNo(refundTradeNo);
            setRefundType(RefundTypeEnum.RentVehicle.getCode());
        }};
        orderRefund.setRefundStatus(refundStatus);
        orderRefundBiz.insertSelective(orderRefund);
    }

    /**
     * 支付回调处理
     * @param orderNo
     * @param tradeNo
     */
    public void payNotifyHandle(String orderNo, String tradeNo) {
        BaseOrder baseOrder = this.selectOne(new BaseOrder() {{
            setNo(orderNo);
        }});

        if (OrderStatusEnum.ORDER_UNPAY.getCode().equals(baseOrder.getStatus()) && baseOrder.getHasPay().equals(SYS_FALSE)) {
            BaseOrder updateOrder = new BaseOrder() {{
                setId(baseOrder.getId());
                setOutTradeNo(tradeNo);
                setHasPay(SYS_TRUE);
                setPayTime(System.currentTimeMillis());
                setVersion(baseOrder.getVersion());
            }};

            //如果是会员订单，则触发会员效益
            if(OrderTypeEnum.MEMBER.getCode().equals(baseOrder.getType())) {
                //直接设置订单完成
                updateOrder.setStatus(OrderStatusEnum.ORDER_FINISH.getCode());
                OrderMemberDetail omd = orderMemberDetailBiz.selectOne(new OrderMemberDetail(){{
                    setOrderId(baseOrder.getId());
                }});

                //触发会员效益
                userFeign.buyMember(new UserMemberDTO() {{
                    setUserId(baseOrder.getUserId());
                    setDiscount(omd.getRebate());
                    setIsBind(ISBIND_BIND);
                    setMemberLevel(omd.getMemberLevel());
                    setRentFreeDays(omd.getRentFreeNum());
                }});
            }else if(OrderTypeEnum.RentVehicle.getCode().equals(baseOrder.getType())) {
                updateOrder.setStatus(OrderStatusEnum.ORDER_TOSTART.getCode());
                OrderRentVehicleDetail orvd = orderRentVehicleBiz.selectOne(new OrderRentVehicleDetail(){{
                    setOrderId(baseOrder.getId());
                }});
                //车辆预定审核通过

                //确认免费天数
                if(orvd.getFreeDays() > 0) {
                    userFeign.memberDays(baseOrder.getUserId(), orvd.getFreeDays(), UserFeign.MEMBER_DAYS_CONFIRM);
                }

            }else if(OrderTypeEnum.TOUR.getCode().equals(baseOrder.getType())) {
                updateOrder.setStatus(OrderStatusEnum.ORDER_TOSTART.getCode());
                OrderTourDetail otd = orderTourDetailBiz.selectOne(new OrderTourDetail(){{
                    setOrderId(baseOrder.getId());
                }});

                //站点总人数添加
                 tourFeign.updateTourGoodPersonNum(otd.getVerificationId(), TourFeign.TOTAL_PERSON, otd.getTotalNumber());
            }
            this.updateSelectiveByIdRe(updateOrder);
        } else {
            log.error(" order has payed , orderNo:{}, tradeNo:{} ", orderNo, tradeNo);
        }
    }
}