package cn.freemud.service;

import cn.freemud.amp.body.OrderBody;
import cn.freemud.annotations.OrderReportType;
import cn.freemud.enums.*;
import cn.freemud.request.ProductRandomVo;
import cn.freemud.request.wechat.dto.IndirectSyncStatusDto;
import cn.freemud.request.wechat.dto.SignMessageBuilder;
import cn.freemud.request.wechat.dto.SyncStatusDto;
import cn.freemud.resposne.SynchronizationOrderResponse;
import cn.freemud.service.thirdparty.WechatMchClient;
import cn.freemud.util.ProductRandomUtil;
import cn.freemud.util.RSAUtils;
import cn.freemud.util.Rfc3339Util;
import com.alibaba.fastjson.JSON;
import com.google.common.collect.Lists;
import com.google.gson.Gson;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.net.URL;
import java.util.Date;
import java.util.List;
import java.util.UUID;

/**
 * All rights Reserved, Designed By www.freemud.cn
 *
 * @version V1.0
 * @Title: ${FILE_NAME}
 * @Package com.freemud.mail.core
 * @Description: ${TODO}(用一句话描述该文件做什么)
 * @author: aiqi.gong
 * @date: 2019/3/21 18:37
 * @Copyright: 2018 www.freemud.cn Inc. All rights reserved.
 * 注意：本内容仅限于上海非码科技内部传阅，禁止外泄以及用于其他的商业目
 */
@Service("wechatOrderPushHandleServiceImpl")
@Slf4j
@OrderReportType(OrderReportEnum.WECHAT)
public class WechatOrderPushHandleServiceImpl implements SynchronizedOrderService {
    /**
     * 商户号
     */
    private static String SPMCHID = "1237482502";
            //syncStatusDto.setSp_mchid("270786433");
    //private static String SPMCHID = "270786433";
    /**
     * 开放平台ID
     */
    private static String SPWXAPPID = "wx8244c7c48c7d45de";
    /**
     * 点餐入口
     */
    private static String ENTRYPAGE = "pages/storeListShop";
    /**
     * 证书序列号
     */
    private static String SERIALNO = "3425DD6C131D637D7316076C4A44E1CBEFE3DB55";
    //private static String SERIALNO="586C0F74293A65ADE34EC4A6209631BC1EA4F7F3";
    /**
     * 私钥
     */
    private static String PRIVATEKEY = "MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDO+3Q6YX6843Qo5Okhum74yG7zpJ8NbWk9EugJwxW9AZuZI3fziAW5+EblEkx0ZeXYX/GvztjRUZ+MA4eHAXnAdzhiTO46LOePtjQXXqPVOHKEhkfa/5qvJSzJ1Ei8ICrA1hQOGF0sqxMmFNpWaXJkHZ7rJ4KRir8osVeWEF8l8xWEktpXVzspT1PGt7T9i9cQO/lMFYP9nq4qr0pZ4rGgpjURjuZHam5E9l6IFP0VVBvyYP96c/9rUgDeLtPqRDCfQC3WYUtA34XudM/HaGCSPvg5ui5Q2sWob10YFP2F8iTCBHDE3rR1s+inYjS4oXd/TCWQ7+C/O7L9h5AKEFAZAgMBAAECggEAGNFJpF5gReG34ddgpKyn9aiCtS/96iw+PBZyQAlmJ91zfK8mCMs8dInyZjEFfcdiAcmvPvc8RAzXZoBd1bA1mwAwgIjc35jWwwKDyHGOj1hPUtiO8RFIyMtaTXDor7Xjqm+AxBfjxCFXEG/bphTKpHpwvZ1lKHJMbWKmL9YSsof1zK12FC5nFxA0mrPlpYHWFmbeMLu7ngDTGEA5AepKv+BZcqMEJGQvAgskGHdsLSd2NoadUQoFz0ZOrXAXlqNQpODUqRTm3besq2ClBaa2JNEG/KxGqZGM11jsTaduH5WhUubb53OJ8pbkw3ROept9fW25QX/k3ORJ3Xmq+g4gAQKBgQDqbRE1mrfEYW0yjnb6FKx+0jHcU/RNuqflCCoWaEzzNJbMzTxuYvyyR7bhT07B26Qji2ic3T/qUokMXpavadZItH8QegTf3eCtDWU1a6RdPkS+NvRT3NaJstbPnGEEavcbS4y45phE9637rhn7WpaWCmw4ggaawNH/lo7kOBCqGQKBgQDiB9PpW7gumtFlNqw6HVcdl/1SvIOWPujvzYNnFkp3ZWDf/hF7XWno3+w27kA/ox9X7A7ejZZgPsR1+QVgbAGCRDs7qVM77r0XddXtKatCnENWsIER11+SAHwXNI+OzVJyivxqc8MqKVt/TdIIRlOXmrDtBLWXrKtJ6+fpRZ2WAQKBgG1T2EbLlRB871Q4pLwUkC3FEYPTk4f8mPhzSk2Q7vItgHaa8Kf6eica0utY9T3rlS0OgwdFF93MCCZApr2/+jOGGgwxG7zb2UBbkuvK+6iQtbaQInpJ77PgN9Yy8/v/dqbAISzKPhFMAVPy6iMTKE9pJPdljHb3nfg42wMMMplhAoGAYV2r3F9FNNY+E1J82D/hUf8yAZzxNhx9bSdjTlnc1BfYpkSktTalM8qZz4PMK12SV+Z49UeamnUPXh5aQZHlCH9p4KZtE2khDWUWNSZ4/qWfoE1CHDRhl9wbmEds+7/YnzzdxOF/Fb9hCbK1IhlhUvIw+rjHnMGlu58idGsnmgECgYAk+2mWAoGUaQdgPHc0Ts8AiZ1CB2HcWEakFD4yYfVYL107OkxfSXd7dlaVklCHbHaMUYuT4euIfJzXfaTjEnImqQu2hs9u1yTyJHKwjj9gyWHYfcr4byiXjKnbwMkNCrrHWMXCKZ3/F0FQWRE9lsIHZYkFUUUoZYmSorbBf815HQ==";

    private static Gson gson = new Gson();


    @Autowired
    private WechatMchClient wechatMchClient;

    /**
     * 数据上送接口调用
     *
     * @param uuid
     * @param orderBody
     * @return
     */
    @Override
    public SynchronizationOrderResponse synchronizationOrder(String uuid, OrderBody orderBody,String mchId,String subMchId,String serialNo,String privateKey,Integer type) {
        SynchronizationOrderResponse synchronizationOrderResponse = new SynchronizationOrderResponse(Boolean.FALSE, null);
        if(type == 2) {
            IndirectSyncStatusDto syncStatusDto = convent2IndirectSyncStatusDtoCreate(orderBody, mchId, subMchId);
            //syncStatusDto.setSub_mchid("301409346");
            if (syncStatusDto == null) {
                return synchronizationOrderResponse;
            }
            String authorizatio = convent2IndirectSign(syncStatusDto, mchId, serialNo, privateKey);
            String request = gson.toJson(syncStatusDto);
            Object result = null;
            try {
                result = wechatMchClient.syncStatus(authorizatio, request);
                log.info("wechatOrderPushHandleServiceImpl request:{};response:{}", JSON.toJSONString(request), JSON.toJSONString(result));
                synchronizationOrderResponse.setResult(Boolean.TRUE);
            } catch (Exception e) {
                log.error("wechatMchClient_syncStatus,请求参数:{}   返回结果:{},异常:{}", request, gson.toJson(result), e);
                synchronizationOrderResponse.setMessage(e.getMessage());
            }
            return synchronizationOrderResponse;
        }else {
            SyncStatusDto syncStatusDto = convent2SyncStatusDtoCreate(orderBody, mchId, subMchId);
            //syncStatusDto.setSub_mchid("301409346");
            if (syncStatusDto == null) {
                return synchronizationOrderResponse;
            }
            String authorizatio = convent2Sign(syncStatusDto, mchId, serialNo, privateKey);
            String request = gson.toJson(syncStatusDto);
            Object result = null;
            try {
                result = wechatMchClient.syncStatus(authorizatio, request);
                log.info("wechatOrderPushHandleServiceImpl request:{};response:{}", JSON.toJSONString(request), JSON.toJSONString(result));
                synchronizationOrderResponse.setResult(Boolean.TRUE);
            } catch (Exception e) {
                log.error("wechatMchClient_syncStatus,请求参数:{}   返回结果:{},异常:{}", request, gson.toJson(result), e);
                synchronizationOrderResponse.setMessage(e.getMessage());
            }
            return synchronizationOrderResponse;
        }
    }




    /**
     * orderBody构造SyncStatusDto
     *
     * @param orderBody 订单信息
     * @return SyncStatusDto 微信上送接口消息体
     */
    public SyncStatusDto convent2SyncStatusDtoCreate(OrderBody orderBody,String mchId,String subMchId) {
        SyncStatusDto syncStatusDto = new SyncStatusDto();
        OrderBody.SyncStatusInfo syncStatusInfo = orderBody.getSyncStatusInfo();
        if (null == syncStatusInfo) {
            log.info("微信上送缺少消息体:{}", syncStatusInfo);
            return null;
        }
        if(StringUtils.isNotEmpty(mchId)) {
            syncStatusDto.setSp_mchid(mchId);
        }else {
            syncStatusDto.setSp_mchid(SPMCHID);
        }
        if(StringUtils.isNotEmpty(subMchId)){
            syncStatusDto.setSub_mchid(subMchId);
        }else {
            syncStatusDto.setSub_mchid(syncStatusInfo.getMchId());
        }

        syncStatusDto.setOrder_entry(ENTRYPAGE);
        syncStatusDto.setSp_appid(SPWXAPPID);
        //syncStatusDto.setSp_appid("wxb78fb7c6218cb52c");
        syncStatusDto.setSub_appid(syncStatusInfo.getWxAppid());
        //todo 支付完成需要填写支付信息
        if (OrderStatus.TAKE_ORDER.getCode().equals(orderBody.getOrderBean().getStatus())) {
            //支付完成
            syncStatusDto.setStatus(WechatSyncStatus.PAY_SUCCESS.getCode());

            syncStatusDto.setTransaction_id(syncStatusInfo.getTransactionId());
            syncStatusDto.setOut_trade_no(syncStatusInfo.getOutTradeNo());
            syncStatusDto.setPay_time(Rfc3339Util.dateToRfc3339(new Date()));

        } else if (OrderStatus.WAIT_PAY.getCode().equals(orderBody.getOrderBean().getStatus())) {
            //支付单创建
            syncStatusDto.setStatus(WechatSyncStatus.CREATE_DEAL.getCode());
        } else {
            //不是下单也不是支付 不需要通知
            return null;
        }

        syncStatusDto.setSub_appid(syncStatusInfo.getWxAppid());
        syncStatusDto.setOut_shop_no(orderBody.getOrderBean().getShopId());
        syncStatusDto.setSub_openid(syncStatusInfo.getOpenId());
        syncStatusDto.setLogin_token(syncStatusInfo.getSessionKey());
        syncStatusDto.setUser_amount(orderBody.getOrderBean().getAmount().intValue());
        syncStatusDto.setPeople_count(1);
        syncStatusDto.setAction_time(Rfc3339Util.dateToRfc3339(new Date()));
        syncStatusDto.setOut_order_no(orderBody.getOrderBean().getOid());
        List<OrderBody.OrderBean.ProductBean> products = orderBody.getOrderBean().getProductList();
        List<SyncStatusDto.DishInfo> list = Lists.newArrayList();
        int priority = 0;
        for (OrderBody.OrderBean.ProductBean productDto : products) {
            SyncStatusDto.DishInfo dishInfo = new SyncStatusDto.DishInfo();
            ProductRandomVo productRandomVo = ProductRandomUtil.getRandomProduct(productDto.getProductId());
            dishInfo.setOut_dish_no(productRandomVo.getId());
            dishInfo.setName(productRandomVo.getName());
            dishInfo.setPrice(productDto.getPrice().intValue());
            dishInfo.setUnit(WechatUnitType.BY_SHARE.getCode());
            dishInfo.setCount(Float.valueOf(productDto.getNumber()));
            dishInfo.setPriority(++priority);
            list.add(dishInfo);
        }
        // 计算优惠金额
        List<OrderBody.OrderBean.AccountBean> accountList = orderBody.getOrderBean().getAccountList();
        int discountAmount = 0;
        if(accountList != null && !CollectionUtils.isEmpty(accountList)) {
            for(OrderBody.OrderBean.AccountBean accountBean : accountList) {
                try {
                    Long price = accountBean.getPrice() == null ? 0 : accountBean.getPrice();
                    if(price < 0) {
                        discountAmount = discountAmount - price.intValue();
                    }
                } catch (Exception e) {
                }
            }
        }
        syncStatusDto.setTotal_amount(discountAmount + orderBody.getOrderBean().getAmount().intValue());
        syncStatusDto.setDiscount_amount(discountAmount);
        syncStatusDto.setDish_list(list);

        return syncStatusDto;
    }

    /**
     * orderBody构造SyncStatusDto
     *
     * @param orderBody 订单信息
     * @return SyncStatusDto 微信上送接口消息体
     */
    public IndirectSyncStatusDto convent2IndirectSyncStatusDtoCreate(OrderBody orderBody, String mchId, String subMchId) {
        IndirectSyncStatusDto syncStatusDto = new IndirectSyncStatusDto();
        OrderBody.SyncStatusInfo syncStatusInfo = orderBody.getSyncStatusInfo();
        if (null == syncStatusInfo) {
            log.info("微信上送缺少消息体:{}", syncStatusInfo);
            return null;
        }
        if(StringUtils.isNotEmpty(mchId)) {
            syncStatusDto.setChannel_id(mchId);
        }else {
            syncStatusDto.setChannel_id(SPMCHID);
        }
        if(StringUtils.isNotEmpty(subMchId)){
            syncStatusDto.setSub_mchid(subMchId);
        }else {
            syncStatusDto.setSub_mchid(syncStatusInfo.getMchId());
        }

        syncStatusDto.setOrder_entry(ENTRYPAGE);
        //syncStatusDto.setSp_appid(SPWXAPPID);
        //syncStatusDto.setSp_appid("wxb78fb7c6218cb52c");
        syncStatusDto.setSub_appid(syncStatusInfo.getWxAppid());
        //todo 支付完成需要填写支付信息
        if (OrderStatus.TAKE_ORDER.getCode().equals(orderBody.getOrderBean().getStatus())) {
            //支付完成
            syncStatusDto.setStatus(WechatSyncStatus.PAY_SUCCESS.getCode());

            syncStatusDto.setTransaction_id(syncStatusInfo.getTransactionId());
            syncStatusDto.setOut_trade_no(syncStatusInfo.getOutTradeNo());
            syncStatusDto.setPay_time(Rfc3339Util.dateToRfc3339(new Date()));

        } else if (OrderStatus.WAIT_PAY.getCode().equals(orderBody.getOrderBean().getStatus())) {
            //支付单创建
            syncStatusDto.setStatus(WechatSyncStatus.CREATE_DEAL.getCode());
        } else {
            //不是下单也不是支付 不需要通知
            return null;
        }

        syncStatusDto.setSub_appid(syncStatusInfo.getWxAppid());
        syncStatusDto.setOut_shop_no(orderBody.getOrderBean().getShopId());
        syncStatusDto.setSub_openid(syncStatusInfo.getOpenId());
        syncStatusDto.setLogin_token(syncStatusInfo.getSessionKey());
        syncStatusDto.setUser_amount(orderBody.getOrderBean().getAmount().intValue());
        syncStatusDto.setPeople_count(1);
        syncStatusDto.setAction_time(Rfc3339Util.dateToRfc3339(new Date()));
        syncStatusDto.setOut_order_no(orderBody.getOrderBean().getOid());
        List<OrderBody.OrderBean.ProductBean> products = orderBody.getOrderBean().getProductList();
        List<IndirectSyncStatusDto.DishInfo> list = Lists.newArrayList();
        int priority = 0;
        for (OrderBody.OrderBean.ProductBean productDto : products) {
            IndirectSyncStatusDto.DishInfo dishInfo = new IndirectSyncStatusDto.DishInfo();
            ProductRandomVo productRandomVo = ProductRandomUtil.getRandomProduct(productDto.getProductId());
            dishInfo.setOut_dish_no(productRandomVo.getId());
            dishInfo.setName(productRandomVo.getName());
            dishInfo.setPrice(productDto.getPrice().intValue());
            dishInfo.setUnit(WechatUnitType.BY_SHARE.getCode());
            dishInfo.setCount(Float.valueOf(productDto.getNumber()));
            dishInfo.setPriority(++priority);
            list.add(dishInfo);
        }
        // 计算优惠金额
        List<OrderBody.OrderBean.AccountBean> accountList = orderBody.getOrderBean().getAccountList();
        int discountAmount = 0;
        if(accountList != null && !CollectionUtils.isEmpty(accountList)) {
            for(OrderBody.OrderBean.AccountBean accountBean : accountList) {
                try {
                    Long price = accountBean.getPrice() == null ? 0 : accountBean.getPrice();
                    if(price < 0) {
                        discountAmount = discountAmount - price.intValue();
                    }
                } catch (Exception e) {
                }
            }
        }
        syncStatusDto.setTotal_amount(discountAmount + orderBody.getOrderBean().getAmount().intValue());
        syncStatusDto.setDiscount_amount(discountAmount);
        syncStatusDto.setDish_list(list);

        return syncStatusDto;
    }

    /**
     * 构造签名
     *
     * @param syncStatusDto 消息体
     * @return 加密签名
     */
    private String convent2Sign(SyncStatusDto syncStatusDto,String mchId,String serialNo,String privateKey) {
        String authorization = null;
        try {
            SignMessageBuilder signMessageBuilder = new SignMessageBuilder()
                    .url(new URL("https://api.mch.weixin.qq.com/v3/catering/orders/sync-status"))
                    .nonceStr(UUID.randomUUID().toString().replace("-", ""))
                    .timestamp(System.currentTimeMillis() / 1000)
                    .httpMethod("POST")
                    .httpBody(gson.toJson(syncStatusDto));


            authorization = getAuthorizationString(signMessageBuilder,mchId,serialNo,privateKey);
        } catch (Exception e) {
            log.error("签名构造异常:{}", e.getStackTrace());
        }
        ;
        return authorization;
    }


    /**
     * 构造签名
     *
     * @param syncStatusDto 消息体
     * @return 加密签名
     */
    private String convent2IndirectSign(IndirectSyncStatusDto syncStatusDto,String mchId,String serialNo,String privateKey) {
        String authorization = null;
        try {
            SignMessageBuilder signMessageBuilder = new SignMessageBuilder()
                    .url(new URL("https://api.mch.weixin.qq.com/v3/catering/orders/sync-status"))
                    .nonceStr(UUID.randomUUID().toString().replace("-", ""))
                    .timestamp(System.currentTimeMillis() / 1000)
                    .httpMethod("POST")
                    .httpBody(gson.toJson(syncStatusDto));


            authorization = getAuthorizationString(signMessageBuilder,mchId,serialNo,privateKey);
        } catch (Exception e) {
            log.error("签名构造异常:{}", e.getStackTrace());
        }
        ;
        return authorization;
    }

    /**
     * 获取Authorization串
     *
     * @param signMessageBuilder 消息体
     * @return 签名
     */
    private String getAuthorizationString(SignMessageBuilder signMessageBuilder,String mchId,String serialNo,String privateKey) {

        String signStr = signMessageBuilder.buildMchSignMessage();
        String signater = null;
        try {
            if(StringUtils.isNotEmpty(privateKey)) {
                signater = RSAUtils.privateEncrypt(signStr, RSAUtils.getPrivateKey(privateKey));
            }else {
                signater = RSAUtils.privateEncrypt(signStr, RSAUtils.getPrivateKey(""));
            }

        } catch (Exception e) {
            log.error("签名加密异常:{}", e.getStackTrace());
        }
        /*String authHeaderValue = "WECHATPAY2-SHA256-RSA2048 "
                + "mchid=\"" + SPMCHID + "\","
                + "nonce_str=\"" + signMessageBuilder.getNonceStr() + "\","
                + "timestamp=\"" + signMessageBuilder.getTimestamp() + "\","
                + "serial_no=\"" + SERIALNO + "\","
                + "signature=\"" + signater + "\"";*/
        StringBuilder sb = new StringBuilder();
        sb.append("WECHATPAY2-SHA256-RSA2048 ");
        if(StringUtils.isNotEmpty(mchId)){
            sb.append("mchid=\"" + mchId + "\",");
        }else {
            sb.append("mchid=\"" + SPMCHID + "\",");
        }
        sb.append("nonce_str=\"" + signMessageBuilder.getNonceStr() + "\",");
        sb.append("timestamp=\"" + signMessageBuilder.getTimestamp() + "\",");
        if(StringUtils.isNotEmpty(serialNo)){
            sb.append("serial_no=\"" + serialNo + "\",");
        }else {
            sb.append("serial_no=\"" +  "\",");
        }
        sb.append("signature=\"" + signater + "\"");

        return sb.toString();
        //return authHeaderValue;
    }


}
