package com.jzdsh.auto.biz;

import com.jfinal.aop.Before;
import com.jfinal.aop.Inject;
import com.jfinal.kit.PropKit;
import com.jfinal.plugin.activerecord.tx.Tx;
import com.jzdsh.auto.model.Orders;
import com.jzdsh.auto.model.UserInfo;
import com.jzdsh.util.Api;
import com.jzdsh.util.CommonCons;
import com.jzdsh.util.CommonUtil;
import com.jzdsh.util.IdWorker;
import com.jzdsh.wxpay.sdk.MyWxPayConfig;
import com.jzdsh.wxpay.sdk.WXPay;
import com.jzdsh.wxpay.sdk.WXPayConstants;
import com.jzdsh.wxpay.sdk.WXPayUtil;
import lombok.extern.log4j.Log4j2;

import java.util.HashMap;
import java.util.Map;

/**
 * @ProjectName: auto
 * @Package: com.jzdsh.auto.biz
 * @ClassName: OrderService
 * @Author: Jzdsh
 * @Description: 订单
 * @Date: 2020/3/25 9:58
 * @Version: 1.0
 */
@Log4j2
public class OrderService {
    @Inject
    UserInfoService userInfoService;

    /**
     * 统一下单
     *
     * @param token
     * @param money
     * @param discount
     * @param pay
     * @param itemService
     * @return
     */
    @Before(Tx.class)
    public Api unifiedOrder(String token, int money, int discount, int pay, String itemService) {

        try {
            token = token.trim( );

            //获取 openid
            UserInfo userInfo = userInfoService.getByToken(token);
            String openid = userInfo.getOpenid( );
            //封装数据对象作返回值
            HashMap< String, Object > map = new HashMap<>(16);
            //保存订单信息
            //-- 认证信息更新完成
            //获取订单编号
            IdWorker idWorker = new IdWorker( );
            long out_trade_no = idWorker.nextId( );

            Orders orders = new Orders( );

            //订单编号
            orders.setOrderNumber(out_trade_no + "");
            //用户id
            orders.setUserId(userInfo.getId( ));
            //支付状态   0未支付1已支付
            orders.setStatus(CommonCons.ORDER_STATUS_ZERO);
            //测试数据默认值 分
            orders.setMoney(money * 100);
            orders.setDiscounts(discount * 100);
            int realPay = pay * 100;
            orders.setPay(realPay);

            //抵扣完金额，付费0
            if (realPay == 0) {
                orders.save( );
                Orders order = Orders.dao.findById(orders.getId( ));

                HashMap< String, String > sub_map = new HashMap<>(16);
                sub_map.put("appId", "");
                //这边要将返回的时间戳转化成字符串
                sub_map.put("timeStamp", "");
                //随机码
                sub_map.put("nonceStr", "");
                //预支付交易会话标识 有效期2h
                sub_map.put("package", "");
                sub_map.put("signType", "");
                sub_map.put("paySign", "");

                //订单展示
                map.put("order", order);
                //返回支付订单信息
                map.put("sub_order", sub_map);
                return Api.ok(map);
            }

            orders.setServiceTime(itemService);
            Map< String, Object > map_order = JSAPIOrder(itemService, realPay, openid, out_trade_no);

            //TODO 优惠券 待写

            //订单展示
            map.put("order", orders);
            //返回支付订单信息
            map.put("sub_order", map_order.get("map_order"));
            return Api.ok(map);
        } catch (Exception e) {
            log.info("", e);
        }
        return Api.fail(null);
    }

    /**
     * 统一下单
     *
     * @param body      商品描述
     * @param total_fee 标价 金额
     * @param openid    用户在该小程序的唯一id
     * @return
     * @throws Exception
     */
    public Map< String, Object > JSAPIOrder(String body, Integer total_fee, String openid, Long out_trade_no) {
        //map封装数据
        HashMap< String, String > map = new HashMap<>( );
        Map< String, Object > returnMap = new HashMap( );
        try {
            Map< String, String > data = new HashMap<>( );
            //商品描述
            data.put("body", body);
            //  标价金额  单位:分
            data.put("total_fee", total_fee + "");
            //用户标识 trade_type=JSAPI，此参数必传，用户在商户appid下的唯一标识
            data.put("openid", openid);
            //商户系统内部订单号
            data.put("out_trade_no", out_trade_no + "");
            //随机字符串，长度要求在32位以内。推荐随机数生成算法
            data.put("nonce_str", WXPayUtil.generateNonceStr( ));
            //支持IPV4和IPV6两种格式的IP地址。调用微信支付API的机器IP
            data.put("spbill_create_ip", CommonUtil.localIp( ));
            // 通知url必须为外网可访问的url，不能携带参数。https://fujinyc.shjieguan.com/nvrnetwork/order/wxNotify
            data.put("notify_url", "https://fujinyc.shjieguan.com");
            data.put("trade_type", "JSAPI");
            //交易类型 小程序取值如下：JSAPI
            data.put("sign_type", WXPayConstants.MD5);

            //MyWxPayConfig 配置了一些默认信息 appid,商户号，商户秘钥，请求域名 ..
            MyWxPayConfig myWxPayConfig = new MyWxPayConfig( );
            WXPay wxpay = new WXPay(myWxPayConfig);

            Map< String, String > rMap = wxpay.unifiedOrder(data);

            //----到此下单结束   以下是返回给前端的封装数据，前端接收到该数据调用支付接口
            //返回状态码
            String return_code = rMap.get("return_code");
            String result_code = rMap.get("result_code");
            String nonce_str = rMap.get("nonce_str");

            String timeStamp = String.valueOf(WXPayUtil.getCurrentTimestamp( ));
            if ("SUCCESS".equals(return_code) && return_code.equals(result_code)) {
                map.put("appId", PropKit.get("appid"));
                //这边要将返回的时间戳转化成字符串
                map.put("timeStamp", timeStamp);
                //随机码
                map.put("nonceStr", nonce_str);
                //预支付交易会话标识 有效期2h
                map.put("package", "prepay_id=" + rMap.get("prepay_id"));
                map.put("signType", WXPayConstants.MD5);
                //再次签名，这个签名用于小程序端调用wx.requesetPayment方法
                String sign = WXPayUtil.generateSignature(map, PropKit.get("mch_key"));
                map.put("paySign", sign);

                returnMap.put("map_order", map);
                return returnMap;
            }
        } catch (Exception e) {
            log.error("下单错误！" + e);
        }
        map.put("message", "下单异常");
        return returnMap;
    }
}
