package com.izouma.nineth.web;

import com.alibaba.fastjson.JSONObject;
import com.anji.captcha.util.StringUtils;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.izouma.nineth.domain.PaymentInfo;
import com.izouma.nineth.domain.User;
import com.izouma.nineth.domain.UserFundAccount;
import com.izouma.nineth.dto.TradeTypeDTO;
import com.izouma.nineth.dto.pay.TradeType;
import com.izouma.nineth.dto.pay.UniformPayRequest;
import com.izouma.nineth.dto.pay.UniformPayResult;
import com.izouma.nineth.dto.userfund.BalanceInfoDTO;
import com.izouma.nineth.enums.AccountStatus;
import com.izouma.nineth.exception.BusinessException;
import com.izouma.nineth.lock.RedisLockException;
import com.izouma.nineth.repo.GiftOrderRepo;
import com.izouma.nineth.repo.PaymentInfoRepo;
import com.izouma.nineth.service.*;
import com.izouma.nineth.service.pay.PayHelper;
import com.izouma.nineth.service.pay.UniformPayConstants;
import com.izouma.nineth.service.pay.UniformPayUtil;
import com.izouma.nineth.utils.SecurityUtils;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.mp.api.WxMpService;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.codec.EncoderException;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;

@Controller
@RequestMapping("/payOrder")
@Slf4j
@AllArgsConstructor
public class OrderPayController {
    private final OrderService     orderService;
    private final AssetService     assetService;
    private final WxMpService      wxMpService;
    private final GiftOrderService giftOrderService;
    private final UniformPayUtil uniformPayUtil;
    private GiftOrderRepo giftOrderRepo;
    private PayHelper payHelper;
    private PaymentInfoRepo paymentInfoRepo;
    private SandpayService sandpayService;
    private UserFundAccountForLianlianpayService userFundAccountForLianlianpayService;

    /**
     * 获取支持的交易渠道
     * @return
     */
    @RequestMapping("/getSupportTradeType")
    @ResponseBody
    public List<TradeTypeDTO> getSupportTradeType(){
        List<TradeTypeDTO> tradeTypeList = new ArrayList<>();

        String defaultPlatform = uniformPayUtil.getDefaultPayPlatform();
        if(UniformPayConstants.NOTPAY_PLATFORM.equals(defaultPlatform)){
            //启用钱包功能
            final User user = SecurityUtils.getAuthenticatedUser();
            if(user != null){

                UserFundAccount lianlianAccount = userFundAccountForLianlianpayService.getAccount(user.getId());
                if(lianlianAccount != null && lianlianAccount.getAccountStatus() == AccountStatus.NORMAL){
                    TradeTypeDTO walletpay = new TradeTypeDTO();
                    walletpay.setName(TradeType.WALLET_ACCOUNT.name());
                    walletpay.setDescription("钱包支付");
                    //查询余额
                    try {
                        BalanceInfoDTO balanceInfoDTO = userFundAccountForLianlianpayService.getBalance(lianlianAccount.getUserId());
                        walletpay.setTotalBalance(balanceInfoDTO.getTotalBalance());
                    }catch(Exception e){
                        log.error("查询余额失败：" + e.getMessage());
                    }

                    tradeTypeList.add(walletpay);
                }


                boolean isBindCard = uniformPayUtil.isBindBankCard(user.getId());
                if(isBindCard) {
                    TradeTypeDTO quickpay = new TradeTypeDTO();
                    quickpay.setName(TradeType.QUICK_PAY.name());
                    quickpay.setDescription("快捷支付");
                    tradeTypeList.add(quickpay);
                }


            }

        }else{

            TradeTypeDTO defaultPay = new TradeTypeDTO();
            defaultPay.setName(TradeType.ALIPAY_WAP.name());
            defaultPay.setDescription("默认支付");
            tradeTypeList.add(defaultPay);

        }

        return tradeTypeList;
    }

    @RequestMapping(value = "/alipay_h5", method = RequestMethod.GET)
    @ResponseBody
    public UniformPayResult payOrderAlipayH5(Long id, Model model) throws Exception {
        UniformPayRequest request = UniformPayRequest.builder().orderId(id)
                .tradeType(TradeType.ALIPAY_WAP).build();
        UniformPayResult result = uniformPayUtil.pay(request);
        return result;
    }

    @RequestMapping(value = "/alipay_wx", method = RequestMethod.GET)
    public String payOrderAlipayWx(Long id, Model model,  @RequestHeader(value = "User-Agent") String userAgent) throws Exception {
        detectUA(userAgent, model);
        try {
            UniformPayRequest request = UniformPayRequest.builder().orderId(id)
                    .tradeType(TradeType.ALIPAY_WAP).build();
            UniformPayResult result = uniformPayUtil.pay(request);
            model.addAllAttributes(BeanUtils.describe(result));

        }catch(RedisLockException e){
            model.addAttribute("errMsg", "支付请求频繁，请刷新重试");
        } catch (Exception e) {
            log.error("支付调用失败,订单ID:" + id, e);
            String errorMsg = e.getMessage();
            if(StringUtils.isBlank(errorMsg)){
                errorMsg = "未知错误";
            }
            model.addAttribute("errMsg", errorMsg);
        }
        return "UniformPayHtml";
    }

    /**
     * 快捷支付
     * @param model
     * @param userAgent
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/quickpay", method = RequestMethod.GET)
    public String payOrderQuickpay(Long orderId, Long giftOrderId, Model model,  @RequestHeader(value = "User-Agent") String userAgent) throws Exception {
        detectUA(userAgent, model);
        try {
            if(orderId == null && giftOrderId == null){
                throw new BusinessException("必须指定一个订单ID");
            }

            if(orderId != null && giftOrderId != null){
                throw new BusinessException("普通订单ID和转赠订单ID不能同时指定");
            }

            //快捷支付
            UniformPayRequest request = UniformPayRequest.builder()
                    .orderId(orderId).giftOrderId(giftOrderId)
                    .tradeType(TradeType.QUICK_PAY).build();
            UniformPayResult result = uniformPayUtil.pay(request);
            model.addAllAttributes(BeanUtils.describe(result));
        }catch(RedisLockException e){
            model.addAttribute("errMsg", "支付请求频繁，请刷新重试");
        } catch (Exception e) {
            log.error("支付调用失败,普通订单ID:" + orderId + ",转赠订单ID:" + giftOrderId, e);
            String errorMsg = e.getMessage();
            if(StringUtils.isBlank(errorMsg)){
                errorMsg = "未知错误";
            }
            model.addAttribute("errMsg", errorMsg);
        }
        return "UniformPayHtml";
    }


    @RequestMapping(value = "/alipay_qr", method = RequestMethod.GET)
    @ResponseBody
    public String payOrderAlipayQR(Long id, Model model) throws Exception {
        UniformPayRequest request = UniformPayRequest.builder().orderId(id)
                .tradeType(TradeType.ALIPAY_QR).build();
        UniformPayResult result = uniformPayUtil.pay(request);
        return result.getPayUrl();
    }

    @RequestMapping(value = "/alipay_app", method = RequestMethod.GET)
    @ResponseBody
    public String payOrderAlipayApp(Long id, Model model) throws Exception {
        UniformPayRequest request = UniformPayRequest.builder().orderId(id)
                .tradeType(TradeType.ALIPAY_APP).build();
        UniformPayResult result = uniformPayUtil.pay(request);
        return result.getPayForm();
    }

    @RequestMapping(value = "/weixin_h5")
    public String payOrderWeixinH5(Long id, Model model, @RequestHeader(value = "User-Agent") String userAgent) throws EncoderException, WxPayException {
        throw new BusinessException("接口暂不可用，请刷新后重试");
        //detectUA(userAgent, model);
        //model.addAttribute("payUrl", orderService.payOrderWeixin(id, WxPayConstants.TradeType.MWEB, null));
        //return "WeixinPayHtml";
    }

    @RequestMapping(value = "/weixin")
    @ResponseBody
    public Object payOrderWeixin(@RequestParam Long id, @RequestParam(defaultValue = "wx_lite") String channel,
                                 @RequestParam(required = false) String openId) throws Exception {
        UniformPayRequest.UniformPayRequestBuilder requestBuilder = UniformPayRequest.builder().orderId(id)
                .tradeType(TradeType.WX_LITE).openId(openId);
        if(!"wx_lite".equals(channel)){
            requestBuilder.tradeType(TradeType.WX_PUB);
        }

        UniformPayResult result = uniformPayUtil.pay(requestBuilder.build());
        return result.getPayParams();
    }

    @RequestMapping(value = "/gift/weixin_h5")
    public String payGiftOrderWeixinH5(Long id, Model model, @RequestHeader(value = "User-Agent") String userAgent) {
        detectUA(userAgent, model);
        try{
            UniformPayRequest.UniformPayRequestBuilder requestBuilder = UniformPayRequest.builder().giftOrderId(id)
                    .tradeType(TradeType.WX_LITE);
            UniformPayResult result = uniformPayUtil.pay(requestBuilder.build());
            model.addAllAttributes(BeanUtils.describe(result));
            //String payUrl = result.getPayUrl();
            //model.addAttribute("payUrl", payUrl);
        } catch (Exception e) {
            log.error("支付调用失败,转赠订单ID:" + id, e);
            String errMsg = e.getMessage();
            if(StringUtils.isEmpty(errMsg)){
                errMsg = "未知错误";
            }
            model.addAttribute("errMsg", errMsg);
        }

        //return "WeixinPayHtml";
        return "UniformPayHtml";
    }

    @RequestMapping(value = "/weixin_pc")
    public String payOrderWeixinPC(@RequestParam Long id, @RequestParam String code, Model model) throws WxPayException, EncoderException, WxErrorException {
        throw new BusinessException("接口暂不可用，请刷新后重试");
//        WxMpOAuth2AccessToken accessToken = wxMpService.oauth2getAccessToken(code);
//        WxMpUser user = wxMpService.oauth2getUserInfo(accessToken, null);
//        WxPayMpOrderResult payParams = (WxPayMpOrderResult) orderService.payOrderWeixin(id, WxPayConstants.TradeType.JSAPI, user.getOpenId());
//        model.addAttribute("payParams", JSON.toJSONString(payParams));
//        return "PayOrderPC";
    }

    @RequestMapping(value = "/gift/alipay", method = RequestMethod.GET)
    public String payGiftOrderAlipay(Long id, Model model, @RequestHeader(value = "User-Agent") String userAgent) {
        detectUA(userAgent, model);
        try{
            UniformPayRequest request = UniformPayRequest.builder().giftOrderId(id)
                    .tradeType(TradeType.ALIPAY_WAP).build();
            UniformPayResult result = uniformPayUtil.pay(request);
            model.addAllAttributes(BeanUtils.describe(result));
        } catch (Exception e) {
            log.error("支付调用失败,转赠订单ID:" + id, e);
            String errMsg = e.getMessage();
            if(StringUtils.isEmpty(errMsg)){
                errMsg = "未知错误";
            }
            model.addAttribute("errMsg", errMsg);
        }

        return "UniformPayHtml";
    }


    @RequestMapping(value = "/gift/weixin_pc")
    public String payGiftOrderWeixinPC(@RequestParam Long id, @RequestParam String code, Model model) throws WxPayException, EncoderException, WxErrorException {
        throw new BusinessException("接口暂不可用，请刷新后重试");
//        WxMpOAuth2AccessToken accessToken = wxMpService.oauth2getAccessToken(code);
//        WxMpUser user = wxMpService.oauth2getUserInfo(accessToken, null);
//        WxPayMpOrderResult payParams = (WxPayMpOrderResult) giftOrderService.payOrderWeixin(id, WxPayConstants.TradeType.JSAPI, user.getOpenId());
//        model.addAttribute("payParams", JSON.toJSONString(payParams));
//        return "PayOrderPC";
    }


    @RequestMapping(value = "/gift/weixin")
    @ResponseBody
    public Object payGiftOrderWeixin(@RequestParam Long id, @RequestParam String openId) throws WxPayException, EncoderException {
        throw new BusinessException("接口暂不可用，请刷新后重试");
        //return giftOrderService.payOrderWeixin(id, WxPayConstants.TradeType.JSAPI, openId);
    }



    public void detectUA(String ua, Model model) {
        boolean weixin = Pattern.matches(".*(micromessenger).*", ua.toLowerCase());
        boolean ios = Pattern.matches(".*(ipad|iphone).*", ua.toLowerCase());
        boolean android = Pattern.matches(".*(android).*", ua.toLowerCase());
        model.addAttribute("weixin", weixin);
        model.addAttribute("ios", ios);
        model.addAttribute("android", android);
    }
}
