package com.emato.ich.api;

import com.emato.ich.entity.vo.ExpressSendOrderPickUpDto;
import com.emato.ich.utils.Log;

import com.emato.ich.entity.vo.ConfirmOrderVo;
import com.emato.ich.entity.vo.PreparedOrderVo;
import com.emato.ich.entity.vo.TakeParcelVo;
import com.emato.ich.utils.BaseUtils;
import com.emato.ich.utils.JacksonUtils;
import com.emato.ich.utils.LoggingUtils;
import com.emato.ich.utils.StringUtils;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.zhy.http.okhttp.OkHttpUtils;

import java.io.IOException;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

import okhttp3.Callback;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;

/**
 * 请求ICSP-SERVER的客户端
 */
public class ICSPClient {

    private static final String TAG = ICSPClient.class.getName();

    private static final OkHttpClient client = ICSPClientInnerClass.CLIENT;

    private static final String CLIENT_ID = BaseUtils.getClientId();

    private static final String MEDIA_TYPE_JSON = "application/json; charset=utf-8";

    private ICSPClient() {
    }

    /**
     * 投递员登录
     * @param phone     投递员手机号
     * @param password  密码
     * @param callback  回调
     */
    public static void login(String phone, String password, Callback callback) {

        MediaType mediaType = MediaType.parse(MEDIA_TYPE_JSON);
        String jsonBody = "{\"phone\": \"" + phone + "\", \"password\": \"" + password + "\"}";
        RequestBody requestBody = RequestBody.create(jsonBody, mediaType);
        Request request = postRequest(ICSPApi.LOGIN, requestBody, null);

        client.newCall(request).enqueue(callback);
    }

    /**
     * 获取柜子剩余信息
     * @param token     token
     */
    public static void getCabinetInfo(String token, Callback callback) {
        String jsonBody = "{\"clientId\": \"" + CLIENT_ID + "\"}";
        RequestBody requestBody = RequestBody.create(jsonBody, MediaType.parse(MEDIA_TYPE_JSON));
        Request request = postRequest(ICSPApi.GET_CABINET_INFO, requestBody, token);

        client.newCall(request).enqueue(callback);
    }

    /**
     * 查询寄送订单接口
     * @param token
     * @param postmanMob 投递员手机号
     * @param deliveryCode 用户投递码
     * @param callback
     */
    public static void getExpressSendOrder(String token,String postmanMob ,String deliveryCode ,Callback callback) {
        String jsonBody = "{\"postmanMob\": \"" + postmanMob + "\",\"deliveryCode\":\""+ deliveryCode + "\"}";
        RequestBody requestBody = RequestBody.create(jsonBody, MediaType.parse(MEDIA_TYPE_JSON));
        Request request = postRequest(ICSPApi.GET_EXPRESS_SEND_ORDER, requestBody, token);

        client.newCall(request).enqueue(callback);
    }


    /**
     * 预下单
     * @param token             token
     * @param orderVo           预下单信息
     * @param callback          回调
     */
    public static void preparedOrder(String token, PreparedOrderVo orderVo, Callback callback){

        MediaType mediaType = MediaType.parse(MEDIA_TYPE_JSON);
        ObjectMapper objectMapper = JacksonUtils.objectmapper;
        RequestBody requestBody = null;
        try {
            requestBody = RequestBody.create(objectMapper.writeValueAsString(orderVo), mediaType);
        } catch (JsonProcessingException e) {
            Log.e(TAG, "preparedOrder: 构建预下单请求体错误!", e);
            LoggingUtils.sendErrorLog("业务异常: 构建预下单请求体错误! ", e);
        }

        Request request = postRequest(ICSPApi.PREPARED_ORDER, requestBody, token);

        client.newCall(request).enqueue(callback);
    }


    /**
     * 预下单 无token版本

     * @param orderVo           预下单信息
     * @param callback          回调
     */
    public static void preparedOrder(PreparedOrderVo orderVo, Callback callback){

        MediaType mediaType = MediaType.parse(MEDIA_TYPE_JSON);
        ObjectMapper objectMapper = JacksonUtils.objectmapper;
        RequestBody requestBody = null;
        try {
            requestBody = RequestBody.create(objectMapper.writeValueAsString(orderVo), mediaType);
        } catch (JsonProcessingException e) {
            Log.e(TAG, "preparedOrder: 构建预下单请求体错误!", e);
            LoggingUtils.sendErrorLog("业务异常: 构建预下单请求体错误! ", e);
        }

        Request request = postRequest(ICSPApi.DELIVERY_CODE_PREPARE, requestBody, null);

        client.newCall(request).enqueue(callback);
    }

    /**
     * 确认订单接口 无token版本
     * @param confirmOrderVo    请求体
     * @param callback          回调
     */
    public static void confirmOrder(ConfirmOrderVo confirmOrderVo, Callback callback){

        MediaType mediaType = MediaType.parse(MEDIA_TYPE_JSON);
        ObjectMapper objectMapper = JacksonUtils.objectmapper;
        RequestBody requestBody = null;
        try {
            requestBody = RequestBody.create(objectMapper.writeValueAsString(confirmOrderVo), mediaType);
        } catch (JsonProcessingException e) {
            Log.e(TAG, "confirmOrder: 构建确认下单请求体错误!", e);
            LoggingUtils.sendErrorLog("业务异常: 构建确认下单请求体错误! ", e);
        }

        Request request = postRequest(ICSPApi.DELIVERY_CODE_CONFIRM, requestBody, null);

        client.newCall(request).enqueue(callback);

    }
    /**
     * 确认订单接口
     * @param token             凭证
     * @param confirmOrderVo    请求体
     * @param callback          回调
     */
    public static void confirmOrder(String token, ConfirmOrderVo confirmOrderVo, Callback callback){

        MediaType mediaType = MediaType.parse(MEDIA_TYPE_JSON);
        ObjectMapper objectMapper = JacksonUtils.objectmapper;
        RequestBody requestBody = null;
        try {
            requestBody = RequestBody.create(objectMapper.writeValueAsString(confirmOrderVo), mediaType);
        } catch (JsonProcessingException e) {
            Log.e(TAG, "confirmOrder: 构建确认下单请求体错误!", e);
            LoggingUtils.sendErrorLog("业务异常: 构建确认下单请求体错误! ", e);
        }

        Request request = postRequest(ICSPApi.DELIVERER_ORDER, requestBody, token);

        client.newCall(request).enqueue(callback);

    }


    /**
     * 使用运单号取件接口
     * @param token         凭证
     * @param expressSendOrderPickUpDto  取件请求体
     * @param callback      回调
     */
    public static void takeParcelByExpressNo(String token, ExpressSendOrderPickUpDto expressSendOrderPickUpDto, Callback callback) {

        MediaType mediaType = MediaType.parse(MEDIA_TYPE_JSON);
        ObjectMapper objectMapper = JacksonUtils.objectmapper;
        RequestBody requestBody = null;
        try {
            requestBody = RequestBody.create(objectMapper.writeValueAsString(expressSendOrderPickUpDto), mediaType);
        } catch (JsonProcessingException e) {
            Log.e(TAG, "takeParcel: 构建取件请求体错误!", e);
            LoggingUtils.sendErrorLog("业务异常: 构建取件请求体错误! ", e);
        }

        Request request = postRequest(ICSPApi.TACK_BY_EXPRESS_NO, requestBody, token);

        client.newCall(request).enqueue(callback);

    }

    /**
     * 取件接口
     * @param token         凭证
     * @param takeParcelVo  取件请求体
     * @param callback      回调
     */
    public static void takeParcel(String token, TakeParcelVo takeParcelVo, Callback callback) {

        MediaType mediaType = MediaType.parse(MEDIA_TYPE_JSON);
        ObjectMapper objectMapper = JacksonUtils.objectmapper;
        RequestBody requestBody = null;
        try {
            requestBody = RequestBody.create(objectMapper.writeValueAsString(takeParcelVo), mediaType);
        } catch (JsonProcessingException e) {
            Log.e(TAG, "takeParcel: 构建取件请求体错误!", e);
            LoggingUtils.sendErrorLog("业务异常: 构建取件请求体错误! ", e);
        }

        Request request = postRequest(ICSPApi.TAKE_PARCEL, requestBody, token);

        client.newCall(request).enqueue(callback);

    }

    /**
     * 获取系统配置
     * @param token         凭证
     * @param clientId      客户端id
     * @param callback      回调
     */
    public static void getSystemConfig(String token, String clientId, Callback callback) {

        MediaType mediaType = MediaType.parse(MEDIA_TYPE_JSON);
        RequestBody requestBody = null;
        try {
            requestBody = RequestBody.create("{\"clientId\": \"" + clientId + "\"}", mediaType);
        } catch (RuntimeException e) {
            Log.e(TAG, "takeParcel: 重开柜门未知错误! ", e);
            LoggingUtils.sendErrorLog("业务异常: 重开柜门未知错误! ", e);
        }

        Request request = postRequest(ICSPApi.GET_SYSTEM_CONFIG, requestBody, token);

        client.newCall(request).enqueue(callback);

    }

    /**
     * 下载APK
     * @param url               下载链接
     * @param callback          请求回调
     */
    public static void download(final String url, Callback callback) {

        Request request = getRequest(url, "");

        client.newCall(request).enqueue(callback);

    }

    /**
     * 请求图片
     * @param url               url
     * @param callback          回调
     */
    public static void getWeChatMPImage(final String url, Callback callback){

        Request request = getRequest(url, "");

        client.newCall(request).enqueue(callback);

    }

    /**
     * 根据运单号获取用户手机号
     * @param token         凭证
     * @param clientId      客户端id
     * @param mailNo        运单号
     * @param callback      回调
     */
    public static void getUserPhoneNumber(String token, String clientId, String mailNo, Callback callback) {

        MediaType mediaType = MediaType.parse(MEDIA_TYPE_JSON);
        RequestBody requestBody = null;

        try {
            requestBody = RequestBody.create("{\"mailNo\": \"" + mailNo + "\"}", mediaType);
        } catch (RuntimeException e) {
            Log.e(TAG, "getUserPhoneNumber: 获取用户手机号异常! ", e);
            LoggingUtils.sendErrorLog("业务异常: 获取用户手机号异常! ", e);
        }

        Request request = postRequest(ICSPApi.GET_USER_PHONE_NUMBER, requestBody, token);

        client.newCall(request).enqueue(callback);

    }


    /**
     * 投递员付款
     * @param token         凭证
     * @param authCode      支付码
     * @param callback      回调
     */
    public static void delivererPay(String token, String authCode, Callback callback) {

        MediaType mediaType = MediaType.parse(MEDIA_TYPE_JSON);
        RequestBody requestBody = null;

        try {
            requestBody = RequestBody.create("{\"authCode\": \"" + authCode + "\"}", mediaType);
        } catch (RuntimeException e) {
            Log.e(TAG, "delivererPay: 投递员付款异常! ", e);
            LoggingUtils.sendErrorLog("业务异常: 投递员付款异常! ", e);
        }

        Request request = postRequest(ICSPApi.DELIVERER_PAY, requestBody, token);

        client.newCall(request).enqueue(callback);

    }


    public static String isSuccessfulAndParseResponse(Response response) {

        if (null != response && response.isSuccessful()) {
            try {
                return Objects.requireNonNull(response.body()).string();
            } catch (IOException e) {
                Log.e(TAG, "parseResponse: 解析响应信息失败!", e);
                LoggingUtils.sendErrorLog("业务异常: 解析响应信息失败! ", e);
            }
        }
        return "";
    }


    private static Request getRequest(String url, String token) {
        Request.Builder builder = new Request.Builder().url(url).get();

        if (!StringUtils.isNullOrEmpty(token)) {
            builder.addHeader("deliverer_token", token);
        }
        return builder.build();
    }

    private static Request postRequest(String url, RequestBody requestBody, String token){
        Request.Builder builder = new Request.Builder().url(url).post(requestBody);

        if (!StringUtils.isNullOrEmpty(token)) {
            builder.addHeader("deliverer_token", token);
        }
        return builder.build();
    }

    public static OkHttpClient getInstance(){
        return ICSPClientInnerClass.CLIENT;
    }

    static class ICSPClientInnerClass{
        // 重试 超时时间1min 读取超时1min
        private static final OkHttpClient CLIENT = new OkHttpClient.Builder().retryOnConnectionFailure(true).connectTimeout(60, TimeUnit.SECONDS)
                .readTimeout(60, TimeUnit.SECONDS).build();

    }
}
