package com.xingxi.api.controller;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyV3Result;
import com.github.binarywang.wxpay.service.WxPayService;
import com.xingxi.api.common.BaseApiController;
import com.xingxi.api.model.*;
import com.xingxi.api.service.OrderServiceI;
import com.xingxi.business.Order.domain.Order;
import com.xingxi.business.Order.service.IOrderService;
import com.xingxi.business.PaymentInfo.domain.PaymentInfo;
import com.xingxi.business.PaymentInfo.service.IPaymentInfoService;
import com.xingxi.common.enums.EOrderStatus;
import com.xingxi.common.enums.ETradeState;
import com.xingxi.common.utils.DateUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StreamUtils;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.HashMap;

@Slf4j
@RequiredArgsConstructor
@RestController
@RequestMapping("/api/store/order")
public class OrderApiController extends BaseApiController {

    private final OrderServiceI orderServiceI;
    @Autowired
    private IPaymentInfoService paymentInfoService;
    @Autowired
    private WxPayService wxPayService;
    @Autowired
    private IOrderService orderService;
    @Autowired
    private ObjectMapper objectMapper;

    @PostMapping("/orders")
    public OrderQueryResponse getOrderList(@Valid @RequestBody OrderQueryRequest request) {

        return orderServiceI.list(getUserContext(), request);
    }

    @PostMapping("/create")
    public OrderCreateResponse create(@Valid @RequestBody OrderCreateRequest request){
        return orderServiceI.create(getUserContext(), request);
    }


    @GetMapping("/detail")
    public OrderDetailResponse detail(OrderDetailRequest request){
        return orderServiceI.get(getUserContext(), request);
    }

    // 微信支付支付通知接口
    @PostMapping("/wxpay/callback")
    public void callback(HttpServletRequest request, HttpServletResponse response) {
        Date nowDate = DateUtils.getNowDate();

        try {
            String notifyData = StreamUtils.copyToString(request.getInputStream(), StandardCharsets.UTF_8);
            WxPayOrderNotifyV3Result rV3Result = wxPayService.parseOrderNotifyV3Result(notifyData, null);
            WxPayOrderNotifyV3Result.DecryptNotifyResult result = rV3Result.getResult();
            String outTradeNo = result.getOutTradeNo();

            // 通过outTradeNo查找paymentInfo
            PaymentInfo paymentInfo = orderServiceI.selectPaymentInfoByOutTradeNo(outTradeNo);

            // 通过outTradeNo更新订单状态
            Order order = orderService.selectOrderByOrderId(paymentInfo.getOrderId());

            if (EOrderStatus.PAYED.getVal().equals(order.getOrderStatus())) {
                // 如果状态已修改，则返回
                return;
            }

            paymentInfo.setSuccessTime(nowDate);
            paymentInfo.setTransactionId(result.getTransactionId());
            paymentInfo.setTradeType(result.getTradeType());
            paymentInfo.setTradeState(result.getTradeState());
            paymentInfo.setTradeStateDesc(result.getTradeStateDesc());
            paymentInfo.setBankType(result.getBankType());
            paymentInfo.setSuccessTime(DateUtils.parseDate(result.getSuccessTime()));

            paymentInfo.setUpdateUser("WXPAY");
            paymentInfo.setUpdateTime(nowDate);

            paymentInfoService.updatePaymentInfo(paymentInfo);

            if (ETradeState.SUCCESS.getVal().equals(result.getTradeState())) {
                // 支付成功
                //锁数据 for update
                order = orderServiceI.lockOrderByPrescId(order.getOrderId());

                order.setPayTime(nowDate);
                order.setOrderStatus(EOrderStatus.PAYED.getVal());
                order.setUpdateTime(nowDate);
                order.setUpdateUser("WXPAY");
                orderService.updateOrder(order);

            }

        } catch (Exception e) {
            log.error(e.getMessage());
            try {
                buildFailResult(response);
            } catch (Exception e1) {
                log.error(e1.getMessage());
            }
        }
    }

    private void buildFailResult(HttpServletResponse response) throws Exception {
        response.setStatus(400);
        response.getWriter().write(objectMapper.writeValueAsString(new HashMap<String, String>() {
            {
                put("code", "FAIL");
                put("message", "失败");
            }
        }));
    }

}
