package com.bohuikeji.delivery.backstage.controller.open;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.bohuikeji.delivery.backstage.controller.api.customer.CustomerV2Api;
import com.bohuikeji.delivery.backstage.entity.*;
import com.bohuikeji.delivery.backstage.service.*;
import com.bohuikeji.delivery.backstage.service.third.ThirdUtils;
import com.bohuikeji.frame.module.admin.base.ApiController;
import com.bohuikeji.frame.module.admin.utils.MapUtils;
import com.bohuikeji.frame.module.admin.utils.StringUtils;
import io.swagger.annotations.Api;
import jodd.http.HttpRequest;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import java.math.BigDecimal;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.UUID;

/**
 * 海底捞。客如云开放平台
 */
@Api(tags = {"海底捞"})
@Slf4j
@RestController
@RequiredArgsConstructor
@RequestMapping("/api/open/kry")
public class KeRuYunApi extends ApiController {

    final ITOpenService openService;
    final CustomerV2Api customerV2Api;
    final ITOrderService orderService;
    final ITCustomerService customerService;
    final ITCustomerWalletService walletService;
    final ITPayService payService;
    final ITRefundService refundService;
    /**
     * 生产环境地址
     * "https://openapi.keruyun.com";
     */
    public static final String BASE_URL="https://openapi.keruyun.com";
    /**
     * 授权地址
     */
    public static final String BASE_AOUTH2_URL="https://open.keruyun.com";

    /**
     * 测试环境
     */
    /*public static final String APP_KEY="39b384055ae6dee5d8c76e581a604dca";
    public static final String APP_SECRET="fa0f5306544fdd44c72c67a66d3b0f7b";*/

    /**
     * 生产环境
     */
    public static final String APP_KEY="02491569155012056206da7dc18f3eb6";
    public static final String APP_SECRET="5440830dc05cc77045c23701899d3f7d";

    /**
     * 获取TOKEN
     */
    public static final String API_GET_TOKEN_URL="/open/v1/token/get";
    /**
     * 查询门店详情
     */
    public static final String API_QUERY_SHOP_URL="/open/v1/shop/shopdetails";
    /**
     * 查询订单详情
     */
    public static final String API_QUERY_ORDER_URL="/open/v1/data/order/exportDetail";
    /**
     * 推送订单状态
     */
    public static final String API_status_PUSH_URL="/open/v1/delivery/status/push";

    /**
     * 客如云下单接口
     * @param req
     * @return
     */
    @PostMapping("/order/new")
    public JSONObject createOrder(@RequestBody(required = false) String req, @RequestParam(required = false) Map<String,Object> params){
        //log.error("【客如云下单接口】RequestParam参数=[{}]",params);
        //log.error("【客如云下单接口】RequestBody=[{}]",req);
        if (StringUtils.isBlank(req)){
            log.error("【客如云下单接口】请求BODY为空：[{}]",req);
            return fail(1000,"[请求参数错误]body参数为空!");
        }
        //获取海底捞账户
        TOpen open=openService.getById(3);
        TCustomerWallet wallet=walletService.getByCustomerId(open.getCustemerId());
        //计算钱包余额
        if ((new BigDecimal("6")).compareTo(wallet.getWalletPrice())<0){
            return fail(2006,"账户余额不足，当前余额："+wallet.getWalletPrice());
        }
        JSONObject reqJson=JSONObject.parseObject(req);
        log.error("客如云请求参数：[{}]",req);
        //查询客如云门店信息
        JSONObject shopJson=getShopDetails(reqJson.getString("shopIdenty")).getJSONObject("result");
        TOrder order=new TOrder();
        order.setFranId(open.getFranId());
        order.setPlayerId(open.getCustemerId());
        //生产订单号，格式为：客如云订单号+“HH”+客如云门店ID
        //order.setOrderNum(reqJson.getString("orderId")+"HH"+reqJson.getString("shopIdenty"));
        order.setOrderNum(reqJson.getString("orderId")+"HH"+reqJson.getString("shopIdenty"));
        //设置发件人信息
        order.setMailingName(shopJson.getString("commercialName"));
        order.setMailingPhone(shopJson.getString("commercialContactPhone"));
        String[] magLocation=shopJson.getString("latlong").split(",");
        order.setMailingAddress(MapUtils.getAddressReGeo(magLocation[1]+","+magLocation[0]));
        //设置收件人信息
        order.setReceiptName(reqJson.getString("consigneeName"));
        order.setReceiptPhone(reqJson.getString("consigneePhone"));
        String location=reqJson.getString("addrLng")+","+reqJson.getString("addrLat");
        order.setReceiptAddress(MapUtils.getAddressReGeo(location));
        order.setOrderRemarks(reqJson.getString("remark"));
        order.setCargoWeight(1);
        order.setWorthName("50元");
        order.setOrderChannel(open.getName());
        //初始化订单计费各项
        order=openService.openOrderInit(open.getCustemerId(),order);
        //进行计费
        order=orderService.moneySumNew(order);

        //判断账户余额是否足以支付
        if (order.getOrderExpectPrice().compareTo(wallet.getWalletPrice())>0){
            return fail(2006,"账户余额不足，当前余额："+wallet.getWalletPrice());
        }
        order.setOrderFactPrice(order.getOrderExpectPrice());
        //钱包下单直接存入数据库
        orderService.save(order);
        TPay pay =payService.createBeforePay(order,"业务支付","客户支付","钱包");
        TOrder ord = orderService.getByNum(pay.getMerchantNum());
        payService.walletPay(pay,wallet,ord);
        //向客户推送订阅消息
        orderService.post(ord.getOrderId(), "该订单已从钱包扣款。");
        //设置返回参数值
        JSONObject result=new JSONObject();
        result.put("tpOrderId",order.getOrderNum());
        result.put("orderId",reqJson.getString("orderId"));
        //配送费
        result.put("deliverFee",order.getOrderExpectPrice().multiply(new BigDecimal("100")));
        //优惠金额
        result.put("discountFee",0);
        //实付金额
        result.put("actualFee",order.getOrderExpectPrice().multiply(new BigDecimal("100")));
        return success(result);
    }

    /**
     * 取消订单
     * @param req
     * @param params
     * @return
     */
    @PostMapping("/order/cancel")
    public JSONObject cancelOrder(@RequestBody(required = false) String req, @RequestParam(required = false) Map<String,Object> params){
        log.error("【客如云取消订单接口】RequestParam参数=[{}]",params);
        log.error("【客如云取消订单接口】RequestBody=[{}]",req);
        if (StringUtils.isBlank(req)){
            log.error("【客如云下单接口】请求BODY为空：[{}]",req);
            return fail(1000,"[请求参数错误]body参数为空!");
        }
        JSONObject reqJson=JSONObject.parseObject(req);
        log.error("客如云取消订单参数，请求参数：[{}]",req);

        //配送状态：1待接单,2已接单,3配送中,4已送达,5已取消
        if (reqJson.getIntValue("deliveryStatus")==5){
            String orderNum =reqJson.getString("tpOrderId");
            TOrder order=orderService.getByNum(orderNum);
            order.setOrderStatus("已取消");
            order.setOrderEndTime(LocalDateTime.now());
            orderService.updateById(order);
            TOrderCircu.insertCircu(order);
            ThirdUtils.orderCancelAll(order.getOrderNum());
            List<TPay> tPays = payService.list(new QueryWrapper<TPay>().eq("order_id",order.getOrderId()).eq("pay_status","已支付"));
            if(tPays.size()<1){
                log.error("[客如云回调取消订单错误]未找到订单支付记录，参数：{}",req);
                return success();
            }
            refundService.cancel(order,tPays);
        }
        return success();
    }



    /**
     * 查询门店
     * @param id 门店ID
     * @return
     */
    public static JSONObject getShopDetails(String id){
        Map<String,String> query=new TreeMap<>();
        query.put("appKey",APP_KEY);
        query.put("shopIdenty",id);
        query.put("version","1.0");
        query.put("timestamp",System.currentTimeMillis()+"");
        query.put("sign",sign(query,null,getToken(id)));
        String resStr=HttpRequest.post(BASE_URL+API_QUERY_SHOP_URL).query(query).send().bodyText();
        JSONObject res=JSON.parseObject(resStr);
        if (res.getIntValue("code")!=0){
            log.error("【客如云开放平台错误】查询门店信息错误，返回信息：[{}]",resStr);
            throw new RuntimeException(res.getString("message"));
        }
        return res;
    }

    /**
     * 推送订单状态到客如云——已接单，配送中，已送达
     * @param orderNum
     * @return
     */
    public static JSONObject statusPush(String orderNum, Integer deliveryStatus, TCourier courier,String... msg){
        //客如云特殊订单格式拆分，前半部分为客如云订单，后半部分为，门店ID
        String[] nums=orderNum.split("HH");
        //非客如云格式的订单号则不处理
        if (nums.length<2){
            return null;
        }
        Map<String,String> query=new TreeMap<>();
        query.put("appKey",APP_KEY);
        query.put("shopIdenty",nums[1]);
        query.put("version","1.0");
        query.put("timestamp",System.currentTimeMillis()+"");
        query.put("sign",sign(query,null,getToken(nums[1])));
        JSONObject req=new JSONObject();
        req.put("bizType",1);
        req.put("orderId",nums[0]);
        req.put("tpOrderId",orderNum);
        req.put("deliveryStatus",deliveryStatus);
        if (courier!=null){
            req.put("delivererId",courier.getCourierId());
            req.put("deliverer",courier.getCourierName());
            req.put("delivererPhone",courier.getCourierPhone());
        }
        //如果有取消信息则设置取消
        if (msg.length>0){
            req.put("cancelCode",2);
            req.put("cancelReason",msg[0]);
        }
        String resStr=HttpRequest.post(BASE_URL+API_status_PUSH_URL).query(query).bodyText(req.toJSONString(), MediaType.APPLICATION_JSON_VALUE,"UTF-8").send().bodyText();
        return JSON.parseObject(resStr);
    }

    /**
     * 推送订单状态到客如云——取消订单
     * @param orderNum
     * @param cancelReason
     * @return
     */
    public static JSONObject cancelPush(String orderNum,String cancelReason){
        return statusPush(orderNum,5,null,cancelReason);
    }


    /**
     * 成返回不带参数
     * @return
     */
    private static JSONObject success(){
        JSONObject rt=new JSONObject();
        rt.put("code",0);
        rt.put("message","OK");
        rt.put("messageUuid", UUID.randomUUID().toString());
        return rt;
    }

    /**
     * 成功返回，带参数
     * @param body
     * @return
     */
    private static JSONObject success(JSONObject body){
        JSONObject rt=new JSONObject();
        rt.put("result",body);
        rt.put("code",0);
        rt.put("message","OK");
        rt.put("messageUuid", UUID.randomUUID().toString());
        return rt;
    }

    /**
     * 失败返回
     * @param code 错误代码
     * @param msg 错误信息
     * @return
     */
    private static JSONObject fail(int code,String msg){
        JSONObject rt=new JSONObject();
        rt.put("code",code);
        rt.put("message",msg);
        rt.put("messageUuid",UUID.randomUUID().toString());
        return rt;
    }

    /**
     * 业务签名
     * @param params 参数
     * @param body
     * @param token
     * @return
     */
    public static String sign(Map<String,String> params,String body,String token){
        StringBuilder sortedParams = new StringBuilder();
        params.entrySet().stream().forEachOrdered(paramEntry -> sortedParams.append(paramEntry.getKey()).append(paramEntry.getValue()));
        //若存在requestBody则添加body+body体json字符串 否则忽略
        if (body!=null){
            sortedParams.append("body").append(body);
        }
        //请替换成真实的token
        sortedParams.append(token);
        System.out.println(sortedParams);
        String sign = getSign(sortedParams.toString());
        System.out.println(sign + "       " + sign.length());
        return sign;
    }

    /**
     * 获取Token
     * @return
     */
    public static  String getToken(String shopIdenty){
        Map<String,String> query=new TreeMap<>();
        query.put("appKey",APP_KEY);
        query.put("shopIdenty",shopIdenty);
        query.put("version","1.0");
        query.put("timestamp",System.currentTimeMillis()+"");
        StringBuilder sortedParams = new StringBuilder();
        query.entrySet().stream().forEachOrdered(paramEntry -> sortedParams.append(paramEntry.getKey()).append(paramEntry.getValue()));
        sortedParams.append(APP_SECRET);
        query.put("sign",getSign(sortedParams.toString()));
        String resStr=HttpRequest.get(BASE_URL+API_GET_TOKEN_URL).query(query).send().bodyText();
        log.info("获取ToKEN接口返回：[{}]",resStr);
        JSONObject res=JSON.parseObject(resStr);
        if (res.getIntValue("code")!=0){
            log.error("【客如云开放平台错误】获取订单TOKEN错误，返回信息：[{}]",resStr);
            throw new RuntimeException(res.getString("message"));
        }
        return res.getJSONObject("result").getString("token");
    }

    /**
     * 签名
     * @param str
     * @return
     */
    public static String getSign(String str){
        MessageDigest messageDigest = null;
        try {
            messageDigest = MessageDigest.getInstance("SHA-256");
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        messageDigest.update(str.getBytes());
        byte byteBuffer[] = messageDigest.digest();
        StringBuffer strHexString = new StringBuffer();
        for (int i = 0; i < byteBuffer.length; i++){
            String hex = Integer.toHexString(0xff & byteBuffer[i]);
            if (hex.length() == 1) {
                strHexString.append('0');
            }
            strHexString.append(hex);
        }
        // 得到返回結果
        String SHA256Sign = strHexString.toString();
        return SHA256Sign;
    }


}
