package com.ho.filecenter.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.ho.common.tools.constant.CommonConstant;
import com.ho.common.tools.service.RedisService;
import com.ho.filecenter.common.TransIdGenerator;
import com.ho.filecenter.entity.CardInfo;
import com.ho.filecenter.entity.FlowMonitor;
import com.ho.filecenter.service.CardInfoService;
import com.ho.filecenter.service.MobileApiService;
import com.ho.filecenter.vo.flowMonitor.CardInfoDate;
import com.ho.filecenter.vo.flowMonitor.PackageDetailRespVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.time.DateFormatUtils;
import org.apache.hc.client5.http.classic.methods.HttpPost;
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
import org.apache.hc.client5.http.impl.classic.HttpClients;
import org.apache.hc.core5.http.HttpEntity;
import org.apache.hc.core5.http.io.entity.EntityUtils;
import org.apache.hc.core5.http.io.entity.StringEntity;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author gyan
 * @desc: 移动流量卡实现类
 * @DateTime: 2024/1/16 15:35
 */
@Service
@Slf4j
public class MobileApiServiceImpl implements MobileApiService {

    @Autowired
    private TransIdGenerator transIdGenerator;

    @Autowired
    private RedisService redisService;

    @Autowired
    private CardInfoService cardInfoService;


    @Value("${mobile.appId}")
    String appId;

    @Value("${mobile.password}")
    String password;

    @Value("${mobile.ipAndPort}")
    String ipAndPort;

    @Value("${mobile.version}")
    String version;

    @Override
    public void getMobileAllData(List<FlowMonitor> mobileFlowMonitors) {
        //根据所有的套餐id查询查询卡列表
        for (FlowMonitor mobileFlowMonitor : mobileFlowMonitors) {
            String queryPackage = getQueryPackage(mobileFlowMonitor);
            log.info("queryPackage:" + queryPackage);
            PackageDetailRespVo packageDetailRespVo = analysisPackage(queryPackage);
            List<CardInfoDate> parameter = getParameter(mobileFlowMonitor.getId());
            packageDetailRespVo.setCardInfoList(parameter);
            String key = "flowMonitor:mobile:" + mobileFlowMonitor.getId();
            log.info("flowMonitorKey:" + key);
            log.info("packageDetailRespVo:" + packageDetailRespVo);
            redisService.set(key, packageDetailRespVo);
        }
    }

    //电信的前置
    public List<CardInfoDate> getParameter(int id) {
        List<CardInfoDate> cardInfoList = new ArrayList<>();
        int total = cardInfoService.selectByCardTotal(id);
        double ceil = Math.ceil(total * 1.0 / 50);
        for (int i = 0; i < ceil; i++) {
            int offset = i * 50;
            int pageSize = 50;
            List<CardInfo> cardInfos = cardInfoService.selectByFlowCardList(offset, pageSize, id);
            List<CardInfo> realSrcIdList = cardInfos.stream().filter(h -> null != h.getStationId()).collect(Collectors.toList());
            Map<String, Integer> cardStationMap = realSrcIdList.stream().collect(Collectors.toMap(CardInfo::getCard, CardInfo::getStationId, (k1, k2) -> k2));
            Map<String, Integer> cardIdMap = cardInfos.stream().collect(Collectors.toMap(CardInfo::getCard, CardInfo::getId, (k1, k2) -> k2));
            String queryPackageCardInfo = getQueryPackageCardInfo(cardInfos);
            JSONObject cardInfoObject = JSON.parseObject(queryPackageCardInfo);
            if (cardInfoObject != null) {
                String status = (String) cardInfoObject.get("status");
                Integer statusInteger = Integer.valueOf(status);
                if (CommonConstant.ZERO.equals(statusInteger)) {
                    JSONArray cardInfoJSONArray = (JSONArray) cardInfoObject.get("result");
                    for (int h = 0; h <= cardInfoJSONArray.size(); h++) {
                        JSONObject JSONObject = (JSONObject) cardInfoJSONArray.get(h);
                        JSONArray dataAmountList = (JSONArray) JSONObject.get("dataAmountList");
                        if (!dataAmountList.isEmpty()) {
                            for (int m = 0; m < dataAmountList.size(); m++) {
                                CardInfoDate cardInfoDate = new CardInfoDate();
                                JSONObject dataAmountJSONObject = (JSONObject) dataAmountList.get(m);
                                String dataAmount = (String) dataAmountJSONObject.get("dataAmount");
                                String msisdn = (String) dataAmountJSONObject.get("iccid");
                                cardInfoDate.setCardNo(msisdn);
                                if (cardStationMap.containsKey(msisdn)) {
                                    Integer stationId = cardStationMap.get(msisdn);
                                    cardInfoDate.setStationId(stationId);
                                }
                                if (cardIdMap.containsKey(msisdn)) {
                                    Integer cardId = cardIdMap.get(msisdn);
                                    cardInfoDate.setId(cardId);
                                }
                                cardInfoDate.setUserAmount(dataAmount);
                                String format = DateFormatUtils.format(new Date(), CommonConstant.DATE);
                                cardInfoDate.setUpdateTime(format);
                                cardInfoDate.setStatus(CommonConstant.STATUS_FLAG);
                                cardInfoList.add(cardInfoDate);
                            }
                            break;
                        }
                    }
                }
            }
        }
        return cardInfoList;
    }

    /**
     * 获取登录的token，将token存入缓存(移动)
     *
     * @return
     */
    @Override
    public String getMoveToken() {
        com.alibaba.fastjson.JSONObject json = new com.alibaba.fastjson.JSONObject();
        json.put("appid", appId);
        json.put("password", password);
        String transId = transIdGenerator.generateTransIdForMobile(appId);
        json.put("transid", transId);
        String v1 = json.toJSONString();
        log.info("v1:" + v1);
        String url = "https://api.iot.10086.cn/v5/ec/get/token";
        log.info("url:" + url);
        String token = null;
        try {
            CloseableHttpClient httpClient = HttpClients.createDefault();
            HttpPost httpPost = new HttpPost(url);
            httpPost.addHeader("Content-Type", "application/json");
            httpPost.setEntity(new StringEntity(v1));
            CloseableHttpResponse response = httpClient.execute(httpPost);
            HttpEntity entity = response.getEntity();
            String responseContent = EntityUtils.toString(entity, "UTF-8");
            response.close();
            httpClient.close();
            //{"status":"0","message":"正确","result":[{"token":"749b4f858d6f0ee43f3e2e9dff5062fcb761d37604629d23b8e0d9bac043fbdc","ttl":3600}]}
            JSONObject jsonObject = JSON.parseObject(responseContent);
            String status = (String) jsonObject.get("status");
            Integer statusInteger = Integer.valueOf(status);
            if (CommonConstant.ZERO.equals(statusInteger)) {
                JSONArray result = (JSONArray) jsonObject.get("result");
                for (int i = 0; i <= result.size(); i++) {
                    JSONObject JSONObject = (JSONObject) result.get(i);
                    token = (String) JSONObject.get("token");
                    Integer ttl = (Integer) JSONObject.get("ttl");
                    //将结果存入缓存
                    String redisKey = "flowMonitor:mobile:appId:" + appId;
                    JSONObject jsonRedisObject = new JSONObject();
                    jsonRedisObject.put("token", token);
                    jsonRedisObject.put("ttl", ttl);
                    String format = DateFormatUtils.format(new Date(), CommonConstant.DATE);
                    jsonRedisObject.put("updateTime", format);
                    redisService.hmset(redisKey, jsonRedisObject);
                    //加入缓存时间
                    //redisService.expire(redisKey, 50, TimeUnit.MINUTES);
                    break;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error("移动token获取失败");
        }
        log.info("token:" + token);
        return token;
    }


    /**
     * @return
     * @author CMIOT_API23U04-群组本月套餐内流量使用量实时查询
     */
    @Override
    public String getQueryPackage(FlowMonitor flowMonitor) {
        // 请求具体的接口名称
        String apiName = "/ec/query/group-data-margin";
        String redisKey = "flowMonitor:mobile:appId:" + appId;
        String token = getMoveToken();
/*        String token = null;
        Boolean flag = redisService.hasKey(redisKey);
        if (flag) {
            Map<Object, Object> hgetall = redisService.hgetall(redisKey);
            if (hgetall.containsKey("token")) {
                token = (String) hgetall.get("token");
            }
        } else {
            token = getMoveToken();
        }*/
        String transId = transIdGenerator.generateTransIdForMobile(appId);
        // 封装请求接口的参数，需要按实际环境修改
        HashMap<String, String> map = new HashMap<>();
        map.put("transid", transId);
        map.put("token", token);
        map.put("groupId", flowMonitor.getGroupId());
        // 通过参数构造请求URL和参数
        String url = buildUrl(map, ipAndPort, version, apiName);
        // 获取接口返回信息
        String result = sendRequest(url);
        //{"status":"0","message":"正确","result":[{"flowPoolSharingInfo":[{"offeringId":"100019020","offeringName":"2022版高速物联卡全国定向流量6元套餐（共享）","totalAmount":"198180864.00","remainAmount":"185371409.00","useAmount":"12809455.00"}]}]}
        return result;
    }

    /**
     * @return
     * @autho 群组本月套餐内流量使用量实时查询（解析数据）
     */
    @Override
    public PackageDetailRespVo analysisPackage(String res) {
        JSONObject jsonObject = JSON.parseObject(res);
        //{"status":"0","message":"正确","result":[{"flowPoolSharingInfo":[{"offeringId":"100019020","offeringName":"2022版高速物联卡全国定向流量6元套餐（共享）","totalAmount":"198180864.00","remainAmount":"173389002.00","useAmount":"24791862.00"}]}]}
        PackageDetailRespVo packageDetailRespVo = new PackageDetailRespVo();
        if (jsonObject != null) {
            String status = (String) jsonObject.get("status");
            Integer statusInteger = Integer.valueOf(status);
            if (CommonConstant.ZERO.equals(statusInteger)) {
                JSONArray result = (JSONArray) jsonObject.get("result");
                for (int i = 0; i <= result.size(); i++) {
                    JSONObject JSONObject = (JSONObject) result.get(i);
                    if (JSONObject != null) {
                        JSONArray flowPoolSharingInfo = (JSONArray) JSONObject.get("flowPoolSharingInfo");
                        JSONObject flowPoolSharingInfoObject = (JSONObject) flowPoolSharingInfo.get(i);
                        String totalAmount = (String) flowPoolSharingInfoObject.get("totalAmount");
                        log.info("totalAmount:" + totalAmount);
                        String offeringName = (String) flowPoolSharingInfoObject.get("offeringName");
                        log.info("offeringName:" + offeringName);
                        String remainAmount = (String) flowPoolSharingInfoObject.get("remainAmount");
                        log.info("remainAmount:" + remainAmount);
                        String offeringId = (String) flowPoolSharingInfoObject.get("offeringId");
                        String useAmount = (String) flowPoolSharingInfoObject.get("useAmount");
                        log.info("useAmount:" + useAmount);
                        packageDetailRespVo.setRemainAmount(remainAmount);
                        packageDetailRespVo.setTotalAmount(totalAmount);
                        packageDetailRespVo.setUseAmount(useAmount);
                        String format = DateFormatUtils.format(new Date(), CommonConstant.DATE);
                        packageDetailRespVo.setUpdateTime(format);
                        break;
                    }
                }
            }
        }
        return packageDetailRespVo;
    }

    /**
     * @return 查询所有的套餐下卡的当月流量详情（批量查询）
     */
    //(有入参移动套餐的所有的List)
    public String getQueryPackageCardInfo(List<CardInfo> list) {
        // 请求具体的接口名称
        String apiName = "/ec/query/sim-data-usage-monthly/batch";
        String token = getMoveToken();
/*        String redisKey = "flowMonitor:mobile:appId:" + appId;
        String token = null;
        Boolean flag = redisService.hasKey(redisKey);
        if (flag) {
            Map<Object, Object> hgetall = redisService.hgetall(redisKey);
            if (hgetall.containsKey("token")) {
                token = (String) hgetall.get("token");
            }
        } else {
            token = getMoveToken();
        }*/
        String transId = transIdGenerator.generateTransIdForMobile(appId);
        //对于卡号的拼接
        String msisdString = "";
        for (CardInfo cardInfo : list) {
            if (!cardInfo.getCard().isEmpty()) {
                msisdString = msisdString + "_" + cardInfo.getCard();
            }
        }
        String iccids = msisdString.substring(1, msisdString.length());
        //拿取当月时间
        String format = DateFormatUtils.format(new Date(), CommonConstant.DATE).substring(0, 7);
        String replace = format.replace("-", "");
        // 封装请求接口的参数，需要按实际环境修改
        HashMap<String, String> map = new HashMap<>();
        map.put("transid", transId);
        map.put("token", token);
        map.put("iccids", iccids); //msisdns、imsis、iccids 三个参数有且仅有一个即可
        map.put("queryDate", replace); // 仅支持查询近6个月中某月的使用量，其中本月数据截止为前一天
        // 通过参数构造请求URL和参数
        String url = buildUrl(map, ipAndPort, version, apiName);
        // 获取接口返回信息
        String result = sendRequest(url);
        return result;
    }

    /**
     * @return
     * @author 单卡流量池内使用量实时查询(/ ec / query / sim - data - usage - inpool)
     */
    @Override
    public String getSingleCard(String iccid) {
        // 请求具体的接口名称
        //String apiName = "/ec/query/sim-data-margin";
        String apiName = "/ec/query/sim-data-usage-inpool";
        String token = getMoveToken();
      /*  String redisKey = "flowMonitor:mobile:appId:" + appId;
        String token = null;
        Boolean flag = redisService.hasKey(redisKey);
        if (flag) {
            Map<Object, Object> hgetall = redisService.hgetall(redisKey);
            if (hgetall.containsKey("token")) {
                token = (String) hgetall.get("token");
            }
        } else {
            token = getMoveToken();
        }*/
        String transId = transIdGenerator.generateTransIdForMobile(appId);
        // 封装请求接口的参数，需要按实际环境修改
        HashMap<String, String> map = new HashMap<>();
        map.put("transid", transId);
        map.put("token", token);
        map.put("iccid", iccid);
        // 通过参数构造请求URL和参数
        String url = buildUrl(map, ipAndPort, version, apiName);
        // 获取接口返回信息
        String result = sendRequest(url);
        log.info("result:" + result);
        //{"status":"0","message":"正确","result":[{"apnList":[{"apnName":"CMMTMHZCN.JS","apnUseAmount":"513593344"}]}]}
        //return result;
        JSONObject cardInfoObject = JSON.parseObject(result);
        String dataAmount = null;
        if (cardInfoObject != null) {
            String status = (String) cardInfoObject.get("status");
            Integer statusInteger = Integer.valueOf(status);
            if (CommonConstant.ZERO.equals(statusInteger)) {
                JSONArray cardInfoJSONArray = (JSONArray) cardInfoObject.get("result");
                for (int h = 0; h <= cardInfoJSONArray.size(); h++) {
                    JSONObject JSONObject = (JSONObject) cardInfoJSONArray.get(h);
                    JSONArray apnList = (JSONArray) JSONObject.get("apnList");
                    for (int m = 0; m < apnList.size(); m++) {
                        CardInfoDate cardInfoDate = new CardInfoDate();
                        JSONObject dataAmountJSONObject = (JSONObject) apnList.get(m);
                        dataAmount = (String) dataAmountJSONObject.get("apnUseAmount");
                        break;
                    }
                    break;
                }
            }
        }
        return dataAmount;
    }

    /**
     * 工具类
     * 获取请求接口的返回信息
     *
     * @param url 请求接口时需要传入的URL
     */
    public static String sendRequest(String url) {
        InputStream inputStream = null;
        BufferedReader bufferedReader = null;
        HttpURLConnection httpURLConnection = null;
        try {
            URL requestURL = new URL(url);
            // 获取连接
            httpURLConnection = (HttpURLConnection) requestURL.openConnection();
            httpURLConnection.setConnectTimeout(25000); //建立连接的超时时间，毫秒
            httpURLConnection.setReadTimeout(50000);    //获得返回的超时时间，毫秒
            httpURLConnection.setRequestMethod("GET");
            // 通过输入流获取请求的内容
            inputStream = httpURLConnection.getInputStream();
            bufferedReader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
            String temp = null;
            StringBuffer stringBuffer = new StringBuffer();
            // 循环读取返回的结果
            while ((temp = bufferedReader.readLine()) != null) {
                stringBuffer.append(temp);
            }

            return stringBuffer.toString();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //断开连接
            if (httpURLConnection != null) {
                httpURLConnection.disconnect();
            }
            // 关闭流
            if (bufferedReader != null) {
                try {
                    bufferedReader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }

            }
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return null;
    }

    /**
     * 构造请求地址URL
     *
     * @param paramMap 请求参数
     * @return URL
     */
    private static String buildUrl(Map<String, String> paramMap, String ipAndPort, String version, String
            apiName) {
        String url = null;
        StringBuffer urlString = new StringBuffer();
        urlString.append(ipAndPort).append(version).append(apiName);

        if (!paramMap.isEmpty()) {
            log.info("paramMap:" + paramMap);
            // 参数列表不为空，地址尾部增加'?'
            urlString.append('?');
            // 拼接参数
            Set<Map.Entry<String, String>> entrySet = paramMap.entrySet();
            log.info("entrySet:" + entrySet);
            for (Map.Entry<String, String> entry : entrySet) {
                try {
                    urlString.append(entry.getKey()).append('=').append(URLEncoder.encode(entry.getValue(), "UTF-8")).append('&');
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }
            }
            // 去掉最后一个字符“&”
            url = urlString.substring(0, urlString.length() - 1);
        }
        return url;
    }

}
