package cn.iocoder.yudao.module.pms.util;

import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.module.pms.job.IotDeviceCarFuelVO;
import cn.iocoder.yudao.module.pms.job.httpEntity.ApiOilResponse;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.log4j.Log4j;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * @author suiyy
 * @date 20230602
 * @desc 钉钉API接口工具类
 */
@Service
@Log4j
public class ZHBDUtil {
    private static final Logger logger = LoggerFactory.getLogger(ZHBDUtil.class);

    private static final String ID = "NjI1LjUyNS42ODg";
    private static final String SECRET = "3897865b70d7bf29fcca5029147f7d0a";
    private static final String TOKEN_URL = "https://zhbdgps.cn/video/webapi/user/login";
    // 日报表明细
    private static final String LOCATION_URL = "https://zhbdgps.cn/video/webapi/report/fuel/daily/detail";
    // 日报表统计
    private static final String DAILY_FUEL_STATISTICS_URL = "https://zhbdgps.cn/video/webapi/report/fuel/daily/statistics";
    // 查询位置（车牌号）
    private static final String GET_LOCATION_USE_PLATES_URL = "https://zhbdgps.cn/video/webapi/location/get-location-use-plates";
    private static final String parameter = "lng,lat,today_distance,distance,todayoil,totaloil,online,oil1,oil2,oil3,oil4,vehicle_name";

    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private RestTemplate restTemplate;

    /**
     * 获取油耗数据
     * @param carIds 中航北斗 逗号分隔的车辆id
     * @return
     * @throws Exception
     */
    public Map<Integer, IotDeviceCarFuelVO> carFuels(String carIds, String startDate, String endDate) throws Exception {
        String zhbdtoken = redisTemplate.opsForValue().get("zhbdtoken");
        String clientId = redisTemplate.opsForValue().get("zhdbClientId");
        if (StrUtil.isBlank(zhbdtoken) || StrUtil.isBlank(clientId)) {
            Map<String, String> map = new HashMap<>();
            map.put("id", ID);
            map.put("secret", SECRET);
            JSONObject entries = restTemplate.postForObject(TOKEN_URL, map, JSONObject.class);
            if (Objects.nonNull(entries)&&entries.get("code") != null&&Integer.parseInt(String.valueOf(entries.get("code")))==200) {
                JSONObject jsonObject = JSON.parseObject(JSON.toJSONString(entries.get("data")));
                zhbdtoken = jsonObject.get("token").toString();
                // 缓存 client_id
                clientId = jsonObject.get("client_id").toString();
                redisTemplate.opsForValue().set("zhbdtoken", zhbdtoken, 80000, TimeUnit.SECONDS);
                redisTemplate.opsForValue().set("zhdbClientId", clientId, 80000, TimeUnit.SECONDS);
            }
        }
        // 构建请求JSON
        Map<String, Object> requestMap = new HashMap<>();
        requestMap.put("client_ids", clientId);
        requestMap.put("vehicle_ids", carIds);
        requestMap.put("begin_time", startDate);
        requestMap.put("end_time", endDate);
        requestMap.put("page_num", 1);
        requestMap.put("page_size", 10);
        // key车辆carId   value油耗值
        Map<Integer, IotDeviceCarFuelVO> carOilFuelPair = new HashMap<>();
        if (StrUtil.isNotBlank(zhbdtoken)) {
            try {
                String jsonResponse = sendPostRequest(requestMap, zhbdtoken, DAILY_FUEL_STATISTICS_URL);
                ApiOilResponse response = parseResponse(jsonResponse);
                if (response != null && response.code == 200) {
                    List<Map<String, Object>> details = response.data.pageList;
                    // 组装某辆车 某天的油耗
                    for (Map<String, Object> detail : details) {
                        IotDeviceCarFuelVO carFuel = new IotDeviceCarFuelVO();
                        Integer carId = Integer.valueOf(detail.get("vehicle_id").toString());
                        Double oil = Double.valueOf(detail.get("oil").toString());
                        String vehicleName = String.valueOf(detail.get("vehicle_name"));
                        // String createtime = String.valueOf(detail.get("createtime"));
                        carFuel.setVehicleId(carId);
                        carFuel.setVehicleName(vehicleName);
                        carFuel.setOil(oil);
                        // carFuel.setCreatetime(createtime);
                        carOilFuelPair.put(carId, carFuel);
                    }
                }
            } catch (Exception e) {
                log.info("获取油耗数据失败！");
            }
        }
        return carOilFuelPair;
    }

    /**
     * 获取车辆位置 主要是获取车辆的 carId
     * @param plates 中航北斗 车牌号 逗号分隔
     * @return
     * @throws Exception
     */
    public Map<String, Integer> carLocations(String plates) throws Exception {
        String zhbdtoken = redisTemplate.opsForValue().get("zhbdtoken");
        if (StrUtil.isBlank(zhbdtoken)) {
            Map<String, String> map = new HashMap<>();
            map.put("id", ID);
            map.put("secret", SECRET);
            JSONObject entries = restTemplate.postForObject(TOKEN_URL, map, JSONObject.class);
            if (Objects.nonNull(entries)&&entries.get("code") != null&&Integer.parseInt(String.valueOf(entries.get("code")))==200) {
                JSONObject jsonObject = JSON.parseObject(JSON.toJSONString(entries.get("data")));
                zhbdtoken = jsonObject.get("token").toString();
                redisTemplate.opsForValue().set("zhbdtoken", zhbdtoken, 80000, TimeUnit.SECONDS);
            }
        }
        // 构建请求JSON
        Map<String, Object> requestMap = new HashMap<>();
        // 车牌号码 用逗号分隔，例如(示例车牌1,示例车牌2)
        requestMap.put("plates", plates);
        requestMap.put("time", null);

        // key车牌号   value车辆carId
        Map<String, Integer> plateCarIdPair = new HashMap<>();
        if (StrUtil.isNotBlank(zhbdtoken)) {
            try {
                String jsonResponse = sendPostRequest(requestMap, zhbdtoken, GET_LOCATION_USE_PLATES_URL);
                ApiOilResponse response = parseResponse(jsonResponse);
                if (response != null && response.code == 200) {
                    List<Map<String, Object>> locations = response.data.data;
                    // 所有车辆的最后位置信息
                    for (Map<String, Object> detail : locations) {
                        Integer carId = Integer.valueOf(detail.get("vehicle_id").toString());
                        // 车牌号
                        String vehicleName = String.valueOf(detail.get("vehicle_name"));
                        if (StrUtil.isNotBlank(vehicleName) && ObjUtil.isNotEmpty(carId)) {
                            plateCarIdPair.put(vehicleName, carId);
                        }
                    }
                }
            } catch (Exception e) {
                log.info("获取油耗数据失败！");
            }
        }
        return plateCarIdPair;
    }

    private String sendPostRequest(Map<String, Object> requestData, String token, String requestUrl) throws IOException {

        OkHttpClient client = new OkHttpClient();
        ObjectMapper objectMapper = new ObjectMapper();
        String json = objectMapper.writeValueAsString(requestData);
        okhttp3.RequestBody body = okhttp3.RequestBody.create(json, okhttp3.MediaType.parse("application/json"));

        Request request = new Request.Builder()
                .url(requestUrl)
                .post(body)
                .addHeader("Content-Type", "application/json")
                .addHeader("Authorization", "Bearer " + token)// 关键头信息
                .build();
        String responseData = "";
        try (Response response = client.newCall(request).execute()) {
            if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
            responseData = response.body().string();
            System.out.println(responseData);
        } catch (IOException e) {
            e.printStackTrace();
        }

        return responseData;
    }

    private ApiOilResponse parseResponse(String json) throws IOException {
        ObjectMapper mapper = new ObjectMapper();
        return mapper.readValue(json, ApiOilResponse.class);
    }

}
