package com.usoft.fin.grpc.bl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.usoft.fin.grpc.bl.entity.b2b.AcceptItem;
import com.usoft.fin.grpc.bl.entity.b2b.Order;
import com.usoft.fin.grpc.bl.entity.b2b.TokenResult;
import com.usoft.fin.grpc.utils.FinanceGrpcRuntimeException;
import com.usoft.fin.grpc.utils.HttpUtil;
import com.usoft.fin.grpc.utils.VerifyParamsUtil;
import com.usoft.sso.grpc.api.protobuf.SSOGrpcServiceGrpc;
import com.usoft.sso.grpc.api.protobuf.SelectEntInfoRequest;
import com.usoft.sso.grpc.api.protobuf.SelectEntInfoResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.List;
import java.util.Optional;

/**
 * b2b访问业务逻辑
 * @author wangmh
 * @date 2018-09-29 18:42
 */
@Service
public class B2BBl {

    @Value("${b2b.url}")
    public String b2bUrl;

    @Autowired
    private SSOGrpcServiceGrpc.SSOGrpcServiceBlockingStub ssoGSBS;

    /**
     * <pre>
     * 获取当前企业有验收单的订单和订单明细path
     * 可以使用{@link String#format(String, Object...)}拼接
     * 参数说明：
     *     enUU：企业uu号
     *     access_token：根据企业uu号和企业秘钥从b2b获取的access_token，
     *         access_token获取地址：{@link B2BBl#PATH_GET_TOKEN}
     *     excludeAcceptItemIds：不返回的验收单id，逗号分隔
     *     startDate：开始时间-时间戳，没有则填空字符串
     *     endDate：结束时间-时间戳，没有则填空字符串
     * </pre>
     */
    public static final String PATH_ENTERPRISE_ACCEPT_ORDER = "/openapi/api/puchase/orders/withAccepts?enUU=%d&access_token=%s&excludeAcceptItemIds=%s&startDate=%s&endDate=%s";

    /**
     * <pre>
     * 获取指定验收单id的验收单的明细
     * 可以使用{@link String#format(String, Object...)}拼接
     * 参数说明：
     *     enUU：企业uu号
     *     access_token：根据企业uu号和企业秘钥从b2b获取的access_token，
     *         access_token获取地址：{@link B2BBl#PATH_GET_TOKEN}
     *     acceptItemIds：需要返回验收单的验收单id，逗号分隔
     * </pre>
     */
    public static final String PATH_ACCEPT_ORDER = "/openapi/api/puchase/acceptItems?enUU=%d&access_token=%s&acceptItemIds=%s";

    /**
     * <pre>
     * 获取b2b授权token
     * 可以使用{@link String#format(String, Object...)}拼接
     * 参数说明：
     *     id：企业uu号
     *     secret：企业秘钥
     * </pre>
     */
    public static final String PATH_GET_TOKEN = "/openapi/access_token?id=%d&secret=%s";

    /**
     * 获取b2b accessToken
     * @param enuu 企业uu号
     * @return accessToken
     */
    private String getAccessToken(long enuu) {
        // 获取b2b的accessToken
        String responseEntity = null;
        String accessSecret = getAccessSecret(enuu);
        try {
            responseEntity =  HttpUtil.doGet(String.format(b2bUrl + PATH_GET_TOKEN, enuu, accessSecret));
        } catch (IOException e) {
            throw new FinanceGrpcRuntimeException(-1, "b2b获取token异常：" + e.getMessage());
        }
        TokenResult tokenResult = JSONObject.parseObject(responseEntity, TokenResult.class);
        String accessToken = Optional.ofNullable(tokenResult).map(TokenResult::getAccess_token)
                .orElseThrow(() -> new FinanceGrpcRuntimeException(-1, "获取access_token失败"));
        return accessToken;
    }

    /**
     * 获取企业秘钥
     * @param enuu 企业uu号
     * @return 企业秘钥
     */
    private String getAccessSecret(long enuu) {
        // 获取企业秘钥
        SelectEntInfoRequest.Builder ssoBuilder = SelectEntInfoRequest.newBuilder();
        ssoBuilder.setSpaceUU(enuu);
        SelectEntInfoResponse ssoResponse = ssoGSBS.selectEntInfo(ssoBuilder.build());
        if (ssoResponse.getResponseHeader().getCode() != 0) {
            throw new FinanceGrpcRuntimeException(ssoResponse.getResponseHeader().getCode(), ssoResponse.getResponseHeader().getMsg());
        }
        String accessSecret = ssoResponse.getAccessSecret();
        VerifyParamsUtil.hasText(accessSecret, "该企业未授权");
        return accessSecret;
    }

    /**
     * 获取b2b订单列表
     * @param enuu 企业uu号
     * @param excludeAcceptItemIds 去除的验收单id，逗号分隔
     * @return b2b {@linkplain Order 订单}列表
     */
    public List<Order> getOrder(long enuu, String excludeAcceptItemIds){
        String accessToken = getAccessToken(enuu);
        String orderEntity = null;
        try {
            orderEntity = HttpUtil.doGet(String.format(b2bUrl + PATH_ENTERPRISE_ACCEPT_ORDER, enuu, accessToken, excludeAcceptItemIds, "", ""));
        } catch (IOException e) {
            throw new FinanceGrpcRuntimeException(-1, "b2b获取订单异常：" + e.getMessage());
        }
        List<Order> orders = JSON.parseArray(orderEntity, Order.class);
        return orders;
    }

    /**
     * 根据企业uu号和验收单id获取验收单
     * @param enuu 企业uu号
     * @param acceptIds 验收单id
     * @return {@linkplain AcceptItem 验收单}列表
     */
    public List<AcceptItem> getOrderAcceptByIds(long enuu, String acceptIds) {
        String accessToken = getAccessToken(enuu);
        String result = null;
        try {
            result = HttpUtil.doGet(String.format(b2bUrl + PATH_ACCEPT_ORDER, enuu, accessToken, acceptIds));
        } catch (IOException e) {
            throw new FinanceGrpcRuntimeException(-1, "b2b获取验收单异常：" + e.getMessage());
        }
        List<AcceptItem> acceptItems = JSON.parseArray(result, AcceptItem.class);
        return acceptItems;
    }
}
