package com.bailuntec.support;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.bailuntec.domain.constant.CommonConstant;
import com.bailuntec.domain.entity.DcBaseSku;
import com.bailuntec.domain.entity.DcExchangeRate;
import com.bailuntec.domain.enumerate.PlatformType;
import com.bailuntec.domain.example.DcExchangeRateExample;
import com.bailuntec.domain.pojo.*;
import com.bailuntec.mapper.DcExchangeRateMapper;
import com.bailuntec.utils.DigestUtils;
import com.bailuntec.utils.OkHttpUtil;
import com.bailuntec.utils.SessionUtil;
import lombok.extern.slf4j.Slf4j;
import okhttp3.*;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.lang3.StringUtils;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;

@Slf4j
public class CallBailunSystem {

    /**
     * 拿SKU映射
     */
    public static DcBaseSku getSkuInfo(String skus) {
        //SKUMS接口需要的请求参数
        CommonSkuCondition commonSkuConditionDto = new CommonSkuCondition();
        commonSkuConditionDto.setResultType(2);//分页
        commonSkuConditionDto.setStatus(-1);
        commonSkuConditionDto.setIsFinish(-1);
        commonSkuConditionDto.setPage(1);
        commonSkuConditionDto.setPageSize(1);
        //有ResultWare返回发货仓库信息
//        commonSkuConditionDto.setIsResultWare(1);
        //有SKU只查提供的SKU
        commonSkuConditionDto.setSkus(skus);
        OkHttpClient client = OkHttpUtil.getInstance();
        SkuData skuDataDto = new SkuData();
        skuDataDto.setCode(CommonConstant.OBJPRO_CODE);
        skuDataDto.setKey(CommonConstant.ALL_OBJPRO_KEY);
        String data = null;
        try {
            skuDataDto.setData(URLEncoder.encode(JSON.toJSONString(commonSkuConditionDto), "utf8"));//将请求参数转为JSON 再Url编码
            data = URLEncoder.encode(JSON.toJSONString(skuDataDto), "utf8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            throw new RuntimeException("同步SKU信息JSON解析失败", e);
        }
        //第一次MD5加密
        String str = DigestUtils.md5DigestAsHex((CommonConstant.ALL_OBJPRO_KEY + skuDataDto.getData()).getBytes());
        //第二次MD5加密
        String sign = DigestUtils.md5DigestAsHex((CommonConstant.SKU_APPKEY + CommonConstant.OBJPRO_CODE + str).getBytes());
        //真正请求的参数
        LinkedHashMap<String, String> map = new LinkedHashMap<>(3);
        map.put("data", data);
        map.put("appId", CommonConstant.SKU_APPID);
        map.put("sign", sign);
        MediaType mediaType = MediaType.parse("application/json");
        RequestBody body = RequestBody.create(mediaType, JSON.toJSONString(map));
        Response response = null;
        String skuStr = null;
        try {
            Request request = new Request.Builder()
                    .url(CommonConstant.SKU_URL)
                    .post(body)
                    .addHeader("Content-Type", "application/json")
                    .build();
            response = client.newCall(request).execute();
            skuStr = response.body().string();
        } catch (IOException e) {
            e.printStackTrace();
            throw new RuntimeException("调用同步SKU信息接口失败", e);
        } finally {
            if (response != null) {
                response.close();
            }
        }
        if (StringUtils.isNotBlank(skuStr)) {
            JSONObject jsonNode = JSON.parseObject(skuStr);
            Integer resultCode = jsonNode.getIntValue("result_code");
            if (resultCode != null && resultCode == 1) {
                String resultUrlSku = jsonNode.getString("data");
                JSONObject jsonObject1 = null;
                try {
                    jsonObject1 = JSON.parseObject(URLDecoder.decode(resultUrlSku, "utf8"));
                } catch (UnsupportedEncodingException e) {
                    throw new RuntimeException("同步SKU信息JSON解URL编码失败", e);
                }
                List<CommonSkuProductInfo> commonSkuProductInfoList = jsonObject1.getObject("Items", new TypeReference<List<CommonSkuProductInfo>>() {
                });
                if (commonSkuProductInfoList != null && commonSkuProductInfoList.size() > 0) {
                    for (CommonSkuProductInfo skuProductInfo : commonSkuProductInfoList) {
                        DcBaseSku dcBaseSku = new DcBaseSku();
                        try {
                            BeanUtils.copyProperties(dcBaseSku, skuProductInfo);
                        } catch (Exception e) {
                            e.printStackTrace();
                            throw new RuntimeException();
                        }
                        String[] split = null;
                        if (skuProductInfo.getPackingSize() != null) {
                            split = skuProductInfo.getPackingSize().split(",");
                        }
                        dcBaseSku.setBussinessId(dcBaseSku.getSellerId());
                        dcBaseSku.setBussinessName(dcBaseSku.getSellerName());
                        dcBaseSku.setLength((split != null && split.length > 0 && CommonConstant.NUMBER_AND_DECIMAL.matcher(split[0]).matches()) ? new BigDecimal(split[0]) : BigDecimal.ZERO);
                        dcBaseSku.setWidth((split != null && split.length > 1 && CommonConstant.NUMBER_AND_DECIMAL.matcher(split[1]).matches()) ? new BigDecimal(split[1]) : BigDecimal.ZERO);
                        dcBaseSku.setHeight((split != null && split.length > 2 && CommonConstant.NUMBER_AND_DECIMAL.matcher(split[2]).matches()) ? new BigDecimal(split[2]) : BigDecimal.ZERO);
                        dcBaseSku.setWeight(skuProductInfo.getWeight() != null ? skuProductInfo.getWeight() : BigDecimal.ZERO.add(skuProductInfo.getPackingWeight() != null ? skuProductInfo.getPackingWeight() : BigDecimal.ZERO));
                        dcBaseSku.setGmtModified(LocalDateTime.now());
                        return dcBaseSku;
                    }
                }
            }
        }
        return null;
    }


    /**
     * 拿SKU映射
     */
    public static BigDecimal skuMapping() {
        //SKUMS接口需要的请求参数
        SkuMappingCondition skuConditionDto = new SkuMappingCondition();
        skuConditionDto.setResultType(3);
        skuConditionDto.setPlat(PlatformType.Amazon.value());
        skuConditionDto.setPlatSku("UK-FBA-N-8ML-G2-C008,UK-FBA-N-8ML-G2-C018,F4-ARM6-YNMU");
        OkHttpClient client = OkHttpUtil.getInstance();
        SkuData skuDataDto = new SkuData();
        skuDataDto.setCode(CommonConstant.OBJPRO_CODE);
        skuDataDto.setKey(CommonConstant.MAP_OBJPRO_KEY);
        String data = null;
        try {
            skuDataDto.setData(URLEncoder.encode(JSON.toJSONString(skuConditionDto), "utf8"));//将请求参数转为JSON 再Url编码
            data = URLEncoder.encode(JSON.toJSONString(skuDataDto), "utf8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            throw new RuntimeException("取SKU映射参数编码失败", e);
        }
        //第一次MD5加密
        String str = DigestUtils.md5DigestAsHex((CommonConstant.MAP_OBJPRO_KEY + skuDataDto.getData()).getBytes());
        //第二次MD5加密
        String sign = DigestUtils.md5DigestAsHex((CommonConstant.SKU_APPKEY + CommonConstant.OBJPRO_CODE + str).getBytes());
        //真正请求的参数
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("sign", sign);
        jsonObject.put("appId", CommonConstant.SKU_APPID);
        jsonObject.put("data", data);
        MediaType mediaType = MediaType.parse("application/json");
        RequestBody body = RequestBody.create(mediaType, jsonObject.toString());
        Request request = new Request.Builder()
                .url(CommonConstant.SKUMAPPING_URL)
                .post(body)
                .addHeader("Content-Type", "application/json")
                .build();
        Response response = null;
        try {
            response = client.newCall(request).execute();
        } catch (IOException e) {
            e.printStackTrace();
        }
        if (response != null && response.isSuccessful()) {
            JSONObject jsonNode = null;
            try {
                jsonNode = JSON.parseObject(response.body().string());
            } catch (IOException e) {
                throw new RuntimeException("同步SKU信息JSON解析失败", e);
            } finally {
                if (response != null) {
                    response.close();
                }
            }
            Integer resultCode = jsonNode.getIntValue("result_code");
            if (resultCode != null && resultCode == 1) {
                String resultUrlSku = jsonNode.getString("data");
                List<SkuMappingInfo> skuMappingInfoList = null;
                try {
                    skuMappingInfoList = JSON.parseObject(URLDecoder.decode(resultUrlSku, "utf8"), new TypeReference<List<SkuMappingInfo>>() {
                    });
                } catch (UnsupportedEncodingException e) {
                    throw new RuntimeException("同步SKU信息JSON解URL编码失败", e);
                }
                if (skuMappingInfoList != null && skuMappingInfoList.size() > 0) {
                    System.out.println("...");
                }
            }
        }
        return null;
    }

    /**
     * 获取每月月初的汇率
     *
     * @param fromCurrency
     * @param toCurrency
     * @return
     * @throws Exception
     */
    public static BigDecimal getMonthExchangeRate(String fromCurrency, String toCurrency, LocalDateTime queryTime) {

        if (queryTime.isBefore(LocalDateTime.of(2018, 1, 1, 0, 0, 0))) {
            queryTime = LocalDateTime.of(2018, 1, 1, 0, 0, 0);
        }
        queryTime = queryTime.withDayOfMonth(1);
        BigDecimal exchangeRate = null;
        try {
            exchangeRate = getMySqlExchangeRate(fromCurrency, toCurrency, queryTime.toLocalDate());
        } catch (Exception e) {
            log.error("获取月初汇率失败", e);
            throw new RuntimeException("获取" + queryTime + "的汇率失败", e);
        }
        return exchangeRate;
    }

    /**
     * 获取指定日期的汇率
     *
     * @param fromCurrency
     * @param toCurrency
     * @return
     * @throws Exception
     */
    public static BigDecimal getExchangeRate(String fromCurrency, String toCurrency, LocalDateTime queryTime) {
        if (queryTime.isBefore(LocalDateTime.of(2018, 1, 1, 0, 0, 0))) {
            queryTime = LocalDateTime.of(2018, 1, 1, 0, 0, 0);
        }
        BigDecimal exchangeRate = null;
        try {
            exchangeRate = getMySqlExchangeRate(fromCurrency, toCurrency, queryTime.toLocalDate());
        } catch (Exception e) {
            log.error("获取" + queryTime + "的汇率失败", e);
            throw new RuntimeException("获取" + queryTime + "的汇率失败", e);
        }
        return exchangeRate;
    }

    private static BigDecimal getMySqlExchangeRate(String fromCurrency, String toCurrency, LocalDate queryTime) {
        DcExchangeRateMapper mapper = SessionUtil.getSession().getMapper(DcExchangeRateMapper.class);
        DcExchangeRate dcExchangeRate = mapper.selectOneByExample(DcExchangeRateExample.newAndCreateCriteria().andInitCurrenyEqualTo(fromCurrency).andFinalCurrenyEqualTo(toCurrency).andRecordTimeEqualTo(queryTime).example());
        if (dcExchangeRate != null) {
            return dcExchangeRate.getExchangeRate();
        }
        OkHttpClient client = OkHttpUtil.getInstance();
        HashMap<String, String> map = new HashMap<>(3);
        map.put("fromCur", fromCurrency);
        map.put("toCur", toCurrency);
        map.put("date", DateTimeFormatter.ofPattern(CommonConstant.DATE_FORMAT).format(queryTime));
        BigDecimal exchangeRate = null;
        Response responseEntity = null;
        try {
            Request request = new Request.Builder()
                    .url(OkHttpUtil.attachHttpGetParams(CommonConstant.EXCHANGE_RATE_URL, map))
                    .get()
                    .build();
            responseEntity = client.newCall(request).execute();
            exchangeRate = null;
            if (responseEntity != null && responseEntity.isSuccessful()) {
                JSONObject jsonObject = JSON.parseObject(responseEntity.body().string());
                exchangeRate = (BigDecimal) jsonObject.get("rate");
                dcExchangeRate = new DcExchangeRate();
                dcExchangeRate.setInitCurreny(fromCurrency);
                dcExchangeRate.setFinalCurreny(toCurrency);
                dcExchangeRate.setExchangeRate(exchangeRate);
                dcExchangeRate.setRecordTime(queryTime);
                try {
                    mapper.insertSelective(dcExchangeRate);
                    SessionUtil.getSession().commit();
                } catch (Exception e) {
                    throw new RuntimeException("Mybatis操作DB失败", e);
                } finally {
                    SessionUtil.closeSession();
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
            throw new RuntimeException("调用汇率接口失败", e);
        } finally {
            if (responseEntity != null) {
                responseEntity.close();
            }
        }
        return exchangeRate;
    }


    /**
     * 返回百伦估算的头程费信息
     *
     * @return
     */
    public static BigDecimal callCostFirstFee(String countryCode, BigDecimal length, BigDecimal width, BigDecimal hight, BigDecimal weight, String lineCode) {
        HashMap<String, String> map = new HashMap<>();
        map.put("endCountries", countryCode);
        map.put("Long", length.toString());
        map.put("width", width.toString());
        map.put("high", hight.toString());
        map.put("WeightKg", weight.toString());
        map.put("electrifiedType", "0");
        map.put("LineCodes", lineCode);
        Response response = null;
        String resultStr = null;
        OkHttpClient client = OkHttpUtil.getInstance();
        try {
            Request request = new Request.Builder()
                    .url(OkHttpUtil.attachHttpGetParams(CommonConstant.FIRST_FEE_URL, map))
                    .get()
                    .build();
            response = client.newCall(request).execute();
            resultStr = response.body().string();
        } catch (IOException e) {
            e.printStackTrace();
            throw new RuntimeException("调用百伦头程费接口失败" + map, e);
        } finally {
            if (response != null) {
                response.close();
            }
        }
        BigDecimal minLogistics = BigDecimal.ZERO;
        if (response != null && response.isSuccessful()) {
            JSONObject jsonObject = JSON.parseObject(resultStr);
            if (jsonObject.get("Data") != null) {
                List<CostFirstModels> costFirstModelsList = jsonObject.getObject("Data", new TypeReference<List<CostFirstModels>>() {
                });
                // 取最低的头程费
                if (costFirstModelsList != null && costFirstModelsList.size() > 0) {
                    BigDecimal min = costFirstModelsList.get(0).getPrice();
                    for (int j = 0; j < costFirstModelsList.size(); j++) {
                        if (min.compareTo(costFirstModelsList.get(j).getPrice()) == 1)
                            min = costFirstModelsList.get(j).getPrice();
                    }
                    minLogistics = min;
                }
            }
            return minLogistics;
        } else {
            throw new RuntimeException("调用百伦LMS系统接口失败" + map);
        }
    }

    /**
     * 拿百伦账号信息
     *
     * @param bailunAccountId
     * @return
     */
    public static AccountNoToken getBailunAccount(Integer bailunAccountId) {
        OkHttpClient client = OkHttpUtil.getInstance();

        Response response = null;
        String resultStr = null;
        try {
            Request request = new Request.Builder()
                    .url(CommonConstant.ACCOUNT_NO_TOKEN_URL + bailunAccountId)
                    .get()
                    .build();
            response = client.newCall(request).execute();
            resultStr = response.body().string();
        } catch (IOException e) {
            e.printStackTrace();
            throw new RuntimeException("调用百伦账号系统接口失败" + bailunAccountId, e);
        } finally {
            if (response != null) {
                response.close();
            }
        }
        if (response != null && response.isSuccessful()) {
            JSONObject jsonObject = JSON.parseObject(resultStr);
            if (jsonObject != null && jsonObject.get("Data") != null) {
                List<AccountNoToken> accountNoTokenList = jsonObject.getObject("Data", new TypeReference<List<AccountNoToken>>() {
                });
                return accountNoTokenList.size() > 0 ? accountNoTokenList.get(0) : null;
            }
        } else {
            throw new RuntimeException("调用百伦账号系统接口失败" + bailunAccountId);
        }
        return null;
    }
}
