package cn.pluss.platform.wechat.impl;

import cn.pluss.platform.api.Result;
import cn.pluss.platform.api.ResultGenerator;
import cn.pluss.platform.device.DeviceOrderInfoService;
import cn.pluss.platform.deviceMerchantBuy.DeviceMerchantBuyService;
import cn.pluss.platform.deviceMerchantBuyDetail.DeviceMerchantBuyDetailService;
import cn.pluss.platform.dto.DeviceMerchantBuyDTO;
import cn.pluss.platform.dto.WechatMerchantAuditDTO;
import cn.pluss.platform.entitiy.ActionInfo;
import cn.pluss.platform.entitiy.Scene;
import cn.pluss.platform.entitiy.WechatQRCode;
import cn.pluss.platform.entity.*;
import cn.pluss.platform.exception.MsgException;
import cn.pluss.platform.merchant.MerchantBaseInfoService;
import cn.pluss.platform.userApp.UserAppService;
import cn.pluss.platform.util.*;
import cn.pluss.platform.wap.HttpUrlConnection;
import cn.pluss.platform.wap.WxPaySignatureUtils;
import cn.pluss.platform.wap.XmlUtil;
import cn.pluss.platform.wechat.WechatService;
import cn.pluss.platform.wechat.WxConstants;
import cn.pluss.platform.wx.WxAccessTokenRequest;
import cn.pluss.platform.wx.WxCommonService;
import cn.pluss.platform.wx.WxCreateQrCodeRequest;
import cn.pluss.platform.wx.WxCreateQrCodeResponse;
import com.alibaba.fastjson.JSONObject;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import javax.servlet.http.HttpServletRequest;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;

/**
 * @author yuchen
 * 
 * @Description
 */
@Slf4j
@Service("wechatService")
public class WechatServiceImpl implements WechatService {

    private static String requestUrl = "https://api.mch.weixin.qq.com/applyment/micro/submit";

    private static final Logger logger = LoggerFactory.getLogger(WechatService.class);

    @Setter(onMethod_ = {@Autowired})
    private UserAppService userAppService;

    @Setter(onMethod_ = {@Autowired})
    private MerchantBaseInfoService merchantBaseInfoService;

    @Setter(onMethod_ = {@Autowired})
    private DeviceOrderInfoService deviceOrderInfoService;

    @Setter(onMethod_ = {@Autowired})
    private DeviceMerchantBuyService deviceMerchantBuyService;

    @Setter(onMethod_ = {@Autowired})
    private DeviceMerchantBuyDetailService deviceMerchantBuyDetailService;

    @Setter(onMethod_ = {@Autowired})
    private WxCommonService wxCommonService;



    @Override
    public Result<Map<String, String>> appPayParam(HttpServletRequest request, Map<String, String> map, DeviceMerchantBuyDTO deviceMerchantBuyDTO) {
        Map<String, String> reMap = appPayParam(request, map);

        boolean createOrder = createOrder(map.get("outTradeNo"), deviceMerchantBuyDTO, request);
        if (createOrder) {
            return ResultGenerator.genSuccessResult(reMap);
        } else {
            throw new MsgException("系统繁忙，请稍后再试");
        }
    }

    @Override
    public Result<Map<String, String>> appPayParamV2(HttpServletRequest request, Map<String, String> map, DeviceMerchantBuyDTO deviceMerchantBuyDTO) {
        Map<String, String> reMap = appPayParam(request, map);

        boolean createOrder = createOrder(map.get("outTradeNo"), deviceMerchantBuyDTO, request);
        if (createOrder) {
            deviceOrderInfoService.createOrder(map.get("outTradeNo") + "", deviceMerchantBuyDTO);
            return ResultGenerator.genSuccessResult(reMap);
        } else {
            throw new MsgException("系统繁忙，请稍后再试");
        }
    }

    @Override
    public Map<String, String> appPayParam(HttpServletRequest request, Map<String, String> map) {
        Map<String, String> result = new HashMap<>(16);
        result.put("appid", ParametersUtil.MERCHANT_APPID);
        result.put("mch_id", ParametersUtil.MERCHANT_PID);
        result.put("nonce_str", StringUtil.genRandomNum(32));
        result.put("body", map.get("body"));
        result.put("out_trade_no", map.get("outTradeNo"));
        result.put("total_fee", (int) (Double.parseDouble(map.get("totalAmount")) * 100) + "");
        result.put("spbill_create_ip", getIpAddress(request));
        result.put("notify_url", ParametersUtil.domain + "/wap/wechat/wechatCallBackV2");
        result.put("trade_type", "APP");
        String sign = WxPaySignatureUtils.signature(result, ParametersUtil.MERCHANT_KEY);
        result.put("sign", sign);
        try {
            String xml = WxPaySignatureUtils.mapToXml(result);
            String httpXML = HttpUrlConnection.httpXML("https://api.mch.weixin.qq.com/pay/unifiedorder", xml);
            if (httpXML == null) {
                throw new MsgException("请求失败，请稍后再试");
            }

            Map<String, Object> parseXMLToMap = XmlUtil.toMap(httpXML);
            if ("SUCCESS".equals(parseXMLToMap.get("return_code"))) {
                if ("SUCCESS".equals((parseXMLToMap.get("result_code")))) {
                    Map<String, String> reMap = new HashMap<>(16);
                    String appid = ParametersUtil.MERCHANT_APPID;
                    String partnerid = ParametersUtil.MERCHANT_PID;
                    String prepayid = (String) parseXMLToMap.get("prepay_id");
                    String packageMsg = "Sign=WXPay";
                    String noncestr = StringUtil.genRandomNum(32);
                    String timeStamp = String.valueOf(System.currentTimeMillis() / 1000);
                    reMap.put("appid", appid);
                    reMap.put("partnerid", partnerid);
                    reMap.put("prepayid", prepayid);
                    reMap.put("package", packageMsg);
                    reMap.put("noncestr", noncestr);
                    reMap.put("timestamp", timeStamp);
                    String signature = WxPaySignatureUtils.signature(reMap, ParametersUtil.MERCHANT_KEY);
                    reMap.put("sign", signature);

                    return reMap;
                } else {
                    throw new MsgException("请求失败，请稍后再试");
                }
            } else {
                throw new MsgException("请求失败，请稍后再试");
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new MsgException("请求失败，请稍后再试");
        }
    }

    /**
     * createOrder:(创建订单). <br/>
     *
     * @param deviceMerchantBuyDTO
     * @return
     * 
     * @author Administrator
     * @since JDK 1.8
     */
    public boolean createOrder(String orderNo, DeviceMerchantBuyDTO deviceMerchantBuyDTO, HttpServletRequest request) {
        DeviceMerchantBuy deviceMerchantBuy = deviceMerchantBuyDTO.convertDeviceMerchantBuy();
        try {
            UserApp userApp = userAppService.queryUserAppByToken();
            Long userId = userApp.getUserId();
            MerchantBaseInfo merchantBaseInfo = new MerchantBaseInfo();
            merchantBaseInfo.setUserId(userId + "");
            List<MerchantBaseInfo> queryMerchantBaseInfoList = merchantBaseInfoService.queryMerchantBaseInfoList(merchantBaseInfo);
            if (queryMerchantBaseInfoList != null && queryMerchantBaseInfoList.size() > 0) {
                merchantBaseInfo = queryMerchantBaseInfoList.get(0);
                deviceMerchantBuy.setMerchantCode(merchantBaseInfo.getMerchantCode());
                deviceMerchantBuy.setMerchantName(merchantBaseInfo.getMerchantName());
            }
            deviceMerchantBuy.setOrderNo(orderNo);
            deviceMerchantBuyService.saveDeviceMerchantBuy(deviceMerchantBuy);
            for (int i = 0; i < deviceMerchantBuyDTO.getQuantity(); i++) {
                DeviceMerchantBuyDetail deviceMerchantBuyDetail = new DeviceMerchantBuyDetail();
                deviceMerchantBuyDetail.setOrderNo(orderNo);
                deviceMerchantBuyDetail.setSoleCode(StringUtil.genRandomNum(3) + StringUtil.getBillno());
                deviceMerchantBuyDetailService.saveDeviceMerchantBuyDetail(deviceMerchantBuyDetail);
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return false;
        }

    }


    /**
     * 从request中获取请求方IP
     *
     * @param request
     * @return
     */
    public static String getIpAddress(HttpServletRequest request) {
        String ip = request.getHeader("x-forwarded-for");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_CLIENT_IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_X_FORWARDED_FOR");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            // 若以上方式均为获取到ip则证明获得客户端并没有采用反向代理直接使用getRemoteAddr()获取客户端的ip地址
            ip = request.getRemoteAddr();
        }
        // 多个路由时，取第一个非unknown的ip
        final String[] arr = ip.split(",");
        for (final String str : arr) {
            if (!"unknown".equalsIgnoreCase(str)) {
                ip = str;
                break;
            }
        }
        return ip;
    }

    @Override
    public Result<String> appRefund(DeviceMerchantBuy deviceMerchantBuy) {
        Map<String, String> wechatMap = new HashMap<String, String>(16);
        String refundNo = StringUtil.genRandomNum(10);
        wechatMap.put("appid", "wxed824282c345b7a0");
        wechatMap.put("mch_id", "1551169371");
        wechatMap.put("nonce_str", StringUtil.genRandomNum(10));
        wechatMap.put("sign_type", "HMAC-SHA256");
        wechatMap.put("out_trade_no", deviceMerchantBuy.getOrderNo());
        wechatMap.put("out_refund_no", refundNo);
        wechatMap.put("total_fee", ((int) (deviceMerchantBuy.getOrderAmount() * 100)) + "");
        wechatMap.put("refund_fee", ((int) (deviceMerchantBuy.getOrderAmount() * 100)) + "");
        wechatMap.put("sign", WechatSignUtil.sha256Sign(wechatMap, ""));
        String resultString = WXPayHttpUtil.WXHttpPostXMLWithCertOrdinary("https://api.mch.weixin.qq.com/secapi/pay/refund", wechatMap, "");
        Map<String, String> resultMap = WXPayXmlUtil.parseXMLToMap(resultString);
        if ("SUCCESS".equalsIgnoreCase(resultMap.get("return_code"))) {
            if ("SUCCESS".equalsIgnoreCase(resultMap.get("result_code"))) {
                deviceMerchantBuy.setStatus("2");
                deviceMerchantBuyService.updateDeviceMerchantBuy(deviceMerchantBuy);
                return ResultGenerator.genSuccessResult("退款成功");
            } else {
                return ResultGenerator.genFailResult("退款失败");
            }
        } else {
            return ResultGenerator.genFailResult("退款失败");
        }
    }

    @Override
    public Result<String> getRQcode(String sceneStr) {
        WxAccessTokenRequest request = WxAccessTokenRequest.buidWxToken(ParametersUtil.APPID,ParametersUtil.APPSECRET,null, WxConstants.ACCESS_TOKEN_URL);
        String accessToken = wxCommonService.getAccessToken(request,false);
        WechatQRCode wechatQRCode = TemporaryQRcode.createForeverTicket(accessToken, 2592000, sceneStr);
        Properties prop = System.getProperties();
        String os = prop.getProperty("os.name");
        String path = null;
        if (os.startsWith("win") || os.startsWith("Win")) {
            // windows目录
            path = "D:/Pictures";
        } else {
            path = ParametersUtil.upload_save_path;
        }

        if (wechatQRCode == null) {
            return ResultGenerator.genFailResult("获取失败");
        }

        try {
            String rQcode = TemporaryQRcode.getRQcode(wechatQRCode.getTicket(), path);
            return ResultGenerator.genSuccessResult(rQcode);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return ResultGenerator.genFailResult("获取失败");
    }

    /**
     * 新获取用
     * @date: 2021/12/9 14:05
     * @param sceneStr:
     * @return cn.pluss.platform.api.Result<java.lang.String>
     */
    @Override
    public Result<String> getNewRQcode(String sceneStr) {
        WxAccessTokenRequest tokenRequest = WxAccessTokenRequest.buidWxToken(ParametersUtil.APPID,ParametersUtil.APPSECRET,null, WxConstants.ACCESS_TOKEN_URL);
        ActionInfo actionInfo = new ActionInfo(new Scene(sceneStr));
        WxCreateQrCodeRequest qrCodeRequest = new WxCreateQrCodeRequest(WxConstants.QR_EXPIRE_SECONDS,WxConstants.QR_STR_SCENE,actionInfo,null,null);
        WxCreateQrCodeResponse wxQrCode = wxCommonService.getWxQrCode(tokenRequest, qrCodeRequest);
        return ResultGenerator.genSuccessResult("获取成功",wxQrCode.getUrl());
    }

    @Override
    public void wechatMerchantAudit(WechatMerchantAuditDTO wechatMerchantAuditDTO) {
//        String userId = wechatMerchantAuditDTO.getUserId();
//        if (StringUtil.isEmpty(userId)) {
//            throw new MsgException("userId参数不存在！");
//        }
//        UserApp userApp = new UserApp();
//        userApp.setUserId(Long.valueOf(userId));
//        List<UserApp> queryUserAppList = userAppService.queryUserAppList(userApp);
//        if (queryUserAppList != null && queryUserAppList.size() > 0) {
//            userApp = queryUserAppList.get(0);// 获取当前用户的信息
//            if (null == userApp.getWechatStatus() || 0 == userApp.getWechatStatus() || 2 == userApp.getWechatStatus()) {
//                MerchantBankCard merchantBankCard = merchantBankCardService.queryMerchantBankCard(userId);
//
//                if (merchantBankCard == null) {
//                    throw new MsgException("请重新进行实名认证，并绑定银行卡");
//                }
//
//                MerchantBaseInfo merchantBaseInfo = new MerchantBaseInfo();
//                merchantBaseInfo.setUserId(userId);
//                List<MerchantBaseInfo> queryMerchantBaseInfoList = merchantBaseInfoService
//                        .queryMerchantBaseInfoList(merchantBaseInfo);
//                if (queryMerchantBaseInfoList == null || queryMerchantBaseInfoList.size() == 0) {
//                    throw new MsgException("请先填写商户基本资料");
//                }
//
//                merchantBaseInfo = queryMerchantBaseInfoList.get(0);
//                MerchantImage mImage = new MerchantImage();
//                mImage.setMerchantCode(merchantBaseInfo.getMerchantCode());
//                List<MerchantImage> queryMerchantImageList = merchantImageService.queryMerchantImageList(mImage);
//                Result<Map<String, Object>> convertUserApp = wechatMerchantAuditDTO.convertMap(merchantBankCard,
//                        merchantBaseInfo, queryMerchantImageList);
//                if (400 == convertUserApp.getCode()) {
//                    throw new MsgException(convertUserApp.getMessage());
//                }
//
//                Map<String, Object> result = convertUserApp.getData();
//                String indoorPic = (String) result.get("09");
//                String storeEntrancePic = (String) result.get("06");
//                String certFullPhoto = (String) result.get("01");
//                String certBacKPhoto = (String) result.get("02");
//                Properties prop = System.getProperties();
//                String os = prop.getProperty("os.name");
//                if (!os.startsWith("win") && !os.startsWith("Win")) {
//                    String REPLACE = ParametersUtil.REPLACE;
//                    indoorPic = indoorPic.replace("https://www.shouyinbei.net", REPLACE);
//                    storeEntrancePic = storeEntrancePic.replace("https://www.shouyinbei.net", REPLACE);
//                    certFullPhoto = certFullPhoto.replace("https://www.shouyinbei.net", REPLACE);
//                    certBacKPhoto = certBacKPhoto.replaceAll("https://www.shouyinbei.net", REPLACE);
//                }
//                indoorPic = WeChatImageUploadUtils.upload(new File(indoorPic));
//                storeEntrancePic = WeChatImageUploadUtils.upload(new File(storeEntrancePic));
//                certFullPhoto = WeChatImageUploadUtils.upload(new File(certFullPhoto));
//                certBacKPhoto = WeChatImageUploadUtils.upload(new File(certBacKPhoto));
//                String businessCode = StringUtil.getBillno();
//                Result<Map<String, String>> registMap = getWechatRegistMap(businessCode, merchantBaseInfo,
//                        merchantBankCard, storeEntrancePic, indoorPic, certFullPhoto, certBacKPhoto);
//                if (400 == registMap.getCode()) {
//                    throw new MsgException(registMap.getMessage());
//                }
//                try {
//                    Map<String, String> registData = registMap.getData();
//                    String resultString = WXPayHttpUtil.WXHttpPostXMLWithCert(requestUrl, registData, keyStoreUrl);
//                    Map<String, String> resultMap = WXPayXmlUtil.parseXMLToMap(resultString);
//                    if ("SUCCESS".equals(resultMap.get("return_code"))) {
//                        if ("SUCCESS".equals(resultMap.get("result_code"))) {
//                            merchantBaseInfo.setApplymentId(resultMap.get("applyment_id"));
//                            userApp.setWechatStatus(1);
//                            if (StringUtil.isNotEmpty(userApp.getParentId())) {// 更新上级推广人的认证商户数量
//                                UserApp parentApp = new UserApp();
//                                parentApp.setUserId(userApp.getParentId());
//                                List<UserApp> queryUserAppList2 = userAppService.queryUserAppList(parentApp);
//                                if (StringUtil.isNotEmpty(userApp.getParentId()) && queryUserAppList2 != null
//                                        && queryUserAppList2.size() > 0) {
//                                    parentApp = queryUserAppList2.get(0);
//                                    UserApp updateParentApp = new UserApp();
//                                    updateParentApp.setId(parentApp.getId());
//                                    updateParentApp.setAuthCount(
//                                            parentApp.getAuthCount() == null ? 1 : parentApp.getAuthCount() + 1);
//                                    userAppService.updateUserApp(updateParentApp);
//                                }
//                            }
//                            throw new MsgException("进件中 请等待审核");
//                        } else {
//                            userApp.setWechatStatus(2);
//                            throw new MsgException(resultMap.get("err_code_des"));
//                        }
//                    } else {
//                        userApp.setWechatStatus(2);
//                        throw new MsgException(resultMap.get("return_code"));
//                    }
//                } catch (Exception e) {
//                    e.printStackTrace();
//                    userApp.setWechatStatus(2);
//                    TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
//                    throw new MsgException("系统繁忙，请联系管理员");
//                } finally {
//                    userAppService.updateUserApp(userApp);
//                    merchantBaseInfo.setWechatRate(ParametersUtil.WECHAT_RATE);
//                    merchantBaseInfoService.updateMerchantBaseInfo(merchantBaseInfo);
//                }
//            } else {
//                throw new MsgException("您已成功进件或者进件正在审核中");
//            }
//        } else {
//            throw new MsgException("该用户不存在");
//        }
    }

    private Result<Map<String, String>> getWechatRegistMap(String businessCode, MerchantBaseInfo merchantBaseInfo,
                                                           MerchantBankCard merchantBankCard, String storeMedia, String indoorPicMedia, String certFullPhoto,
                                                           String certBacKPhoto) {
        log.info("========storeMedia========" + storeMedia);
        log.info("=========storeMedia=====" + indoorPicMedia);
        log.info("=======storeMedia======" + certFullPhoto);
        log.info("=======storeMedia=========" + certBacKPhoto);
        if (StringUtil.isEmpty(storeMedia)) {
            return ResultGenerator.genFailResult("上传出错，请重新上传门头照");
        }
        if (StringUtil.isEmpty(indoorPicMedia)) {
            return ResultGenerator.genFailResult("上传出错，请重新上传门店内照");
        }
        if (StringUtil.isEmpty(certFullPhoto)) {
            return ResultGenerator.genFailResult("上传出错，请重新上传身份证正面照");
        }
        if (StringUtil.isEmpty(certBacKPhoto)) {
            return ResultGenerator.genFailResult("上传出错，请重新上传身份证背面照");
        }
        // 构造入住参数
        Map<String, String> registData = new HashMap<String, String>();
        registData.put("version", "3.0");
        registData.put("cert_sn", "4F3FF2964275BA2D2D8320BC8187FB3E18D22DFE");
        registData.put("mch_id", "1551169371");
        registData.put("nonce_str", StringUtil.genRandomNum(8));
        registData.put("sign_type", "HMAC-SHA256");
        registData.put("business_code", businessCode);
        registData.put("id_card_copy", certFullPhoto);
        registData.put("id_card_national", certBacKPhoto);
        try {
            registData.put("id_card_name", RSAEncryptUtil.rsaEncrypt(merchantBankCard.getBankCertName()));
            registData.put("id_card_number", RSAEncryptUtil.rsaEncrypt(merchantBankCard.getCertNo()));
            registData.put("account_name", RSAEncryptUtil.rsaEncrypt(merchantBankCard.getBankCertName()));
            registData.put("account_number", RSAEncryptUtil.rsaEncrypt(merchantBankCard.getBankCardNo()));
            registData.put("contact", RSAEncryptUtil.rsaEncrypt(merchantBaseInfo.getContactName()));
            registData.put("contact_phone", RSAEncryptUtil.rsaEncrypt(merchantBaseInfo.getContactMobile()));
        } catch (Exception e) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return ResultGenerator.genFailResult("系统繁忙 ，进件失败");
        }
        registData.put("service_phone", merchantBaseInfo.getContactMobile());
        registData.put("id_card_valid_time", "[\"" + merchantBankCard.getCertStartTime().trim() + "\",\""
                + merchantBankCard.getCertEndTime().trim() + "\"]");
        registData.put("account_bank", merchantBankCard.getBankName());
        registData.put("bank_address_code", merchantBankCard.getBankAddressNo());
        registData.put("store_name", merchantBaseInfo.getAlias());
        registData.put("store_address_code", merchantBaseInfo.getAddressNo());
        registData.put("store_street", merchantBaseInfo.getAddress());
        registData.put("store_entrance_pic", storeMedia);
        registData.put("indoor_pic", indoorPicMedia);
        registData.put("merchant_shortname", merchantBaseInfo.getAlias());
        registData.put("product_desc", merchantBaseInfo.getProductDesc());
        registData.put("rate", "0.6%");
        log.info(JSONObject.toJSONString(registData));
        String signString = WechatSignUtil.sha256Sign(registData, "7F05NZBTJ3XNDK5HLSDC3H25ZXOQKDHT");
        registData.put("sign", signString);
        return ResultGenerator.genSuccessResult(registData);
    }
}

