package com.yfd.platform.uavsystem.service.impl;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.yfd.platform.uavsystem.base.BaseApiService;
import com.yfd.platform.uavsystem.data.AccessTokenModel;
import com.yfd.platform.uavsystem.data.MiddleResult;
import com.yfd.platform.uavsystem.enums.WMCenterUrlEnum;
import com.yfd.platform.uavsystem.service.MiddlePlatformService;
import com.yfd.platform.utils.SystemUtils;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;

import javax.servlet.http.HttpServletResponse;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.*;
import java.util.concurrent.TimeUnit;

import static com.yfd.platform.uavsystem.enums.WMCenterUrlEnum.*;
import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
import static org.springframework.http.MediaType.MULTIPART_FORM_DATA_VALUE;

@RestController
@RequestMapping("/zxApi")
@Slf4j
public class MiddlePlatformServiceImpl extends BaseApiService implements MiddlePlatformService {

    @Value("${middle.crud.platform}")
    private String middleHrefByCrud;
    @Value("${middle.crud.tenantId}")
    private String middleTenantIdByCrud;
    @Value("${middle.crud.tenantKey}")
    private String middleTenantKeyByCrud;
    private Middle middle;


    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 是否启用
     */
    @Value("${middle.enable}")
    private boolean enable;

    @Data
    class Middle {
        private String middleHref;
        private String middleTenantId;
        private String middleTenantKey;
    }

    public void setMiddle() {
        if (ObjectUtils.isEmpty(middle)) {
            middle = new Middle();
            middle.setMiddleHref(middleHrefByCrud);
            middle.setMiddleTenantId(middleTenantIdByCrud);
            middle.setMiddleTenantKey(middleTenantKeyByCrud);
        }
    }

    /**
     * <p>
     * 获取token
     * </p>
     *
     * @param refresh 是否需要重新获取
     * @return {@link AccessTokenModel} 报文头信息
     * @Author hu shi hua
     * @date 2024/3/15 14:48
     * @version 1.0.0
     */
    @PostMapping("/getToken")
    public AccessTokenModel getToken(Integer refresh) {
        if (!enable) {
            log.info("调用开关为false");
            return null;
        }
        setMiddle();
        if (ObjectUtil.isEmpty(middle)) {
            log.info("urlMap未找到");
            return null;
        }
        //首先看看redis中有没有token
        Object ztToken = redisTemplate.opsForValue().get("UAV_Token");
        if (ObjectUtil.isNotEmpty(ztToken)) {
            //没过期
            if (ObjectUtil.isEmpty(refresh)) {
                //不需要重新获取
                return JSON.parseObject(ztToken.toString(), AccessTokenModel.class);
            }
        }

        RestTemplate rest = new RestTemplate();
        String uri = WMCenterUrlEnum.GET_TOKEN.getValue();
        //获取token地址
        String reqData = "client_id=${tenantId}&client_secret=${tenantKey}&grant_type=credentials";
        String urlIp = "${gateway}${uri}";

        String tenantKeyEncode = null;

        try {
            tenantKeyEncode = URLEncoder.encode(middle.getMiddleTenantKey(), "UTF-8");
        } catch (UnsupportedEncodingException e) {
            log.error(e.getMessage());;
        }

        log.info(tenantKeyEncode);
        String url = urlIp + "?" + reqData;
        //使用编码过的Key
        url = url.replace("${gateway}", middle.getMiddleHref())
                .replace("${uri}", uri)
                .replace("${tenantId}", middle.getMiddleTenantId())
                .replace("${tenantKey}", tenantKeyEncode);
        log.info(url);

        // 将token放入redis中
        AccessTokenModel tokenModel = null;
        tokenModel = rest.getForObject(url, AccessTokenModel.class);
        if (tokenModel != null) {
            //过期时间预留3分钟
            redisTemplate.opsForValue().set("UAV_Token", JSON.toJSONString(tokenModel), tokenModel.getExpires_in() - (60 * 3), TimeUnit.SECONDS);
        }
        return tokenModel;
    }

    /**
     * <p>
     * 查询操作
     * </p>
     *
     * @param url  调用url
     * @param json 新增参数
     * @return {@link String} 返回结果
     * @Author hu shi hua
     * @date 2024/3/15 15:18
     * @version 1.0.0
     */
    @Override
    @PostMapping("/search")
    public Object queryOperate(WMCenterUrlEnum url, Map<String, Object> json) {
        try {
            MiddleResult filters = new MiddleResult();
            // 获取当前页
            Integer page = Integer.parseInt(json.get("page").toString());
            // 获取页大小
            Integer perPage = Integer.parseInt(json.get("perPage").toString());
            if (ObjectUtil.isNotEmpty(page)) {
                filters.setPage(page);
            }
            if (ObjectUtil.isNotEmpty(perPage)) {
                filters.setPerPage(perPage);
            }

            Object filtersObj = json.get("filters");
            if (ObjectUtil.isNotEmpty(filtersObj)) {
                Map<String, Object> filter = (Map<String, Object>) filtersObj;
                filters.setFilters(filter);
            }
            return publicHttpObj(url, filters);
        } catch (Exception ex) {
            log.error("查询操作时解析json异常。。。。");
            log.error(ex.getMessage());
            log.error(ex.getMessage());
        }
        return null;
    }

    /**
     * <p>
     * 新增、修改、查看操作
     * </p>
     */
    @Override
    public Object addOrEditOrShowOperate(WMCenterUrlEnum url, Map<String, Object> json) {
        return publicHttpObj(url, json);
    }

    /**
     * @param urlEnum 请求地址
     * @param filters 入参
     * @return
     */
    private Object publicHttpObj(WMCenterUrlEnum urlEnum, @RequestBody Object filters) {
        setMiddle();
        if (!enable) {
            return null;
        }

        AccessTokenModel tokenObj = getToken(null);
        String token = tokenObj.getAccess_token();
        String endUrl = middle.getMiddleHref() + urlEnum.getUrl();

        String body = JSON.toJSONString(filters);
        log.info("调用参数：" + body);

        Object o = null;
        try {
            o = postHttp(endUrl, filters, token);
        } catch (Exception e) {
            String error = e.getMessage();
            o = error;
            if (error.contains("423")) {
                getToken(1);
            }
        }
        //日志
        return o;
    }


    private Object postHttp(String url, Object data, String token) {
        RestTemplate rest = new RestTemplate();
        HttpHeaders header = new HttpHeaders();
        header.add("x-token", token);
        header.add(HttpHeaders.CONTENT_TYPE, "application/json;charset=UTF-8");
        String body = JSON.toJSONString(data);  // 在此加入接口的请求参数实体
        HttpEntity<String> entity = new HttpEntity<String>(body, header);
        Object o = null;
        try {
            o = rest.exchange(url, HttpMethod.POST, entity, Object.class);//可以指定服务响应对应的反序列化数据格式代替 Object
        } catch (Exception e) {
            log.error("调用异常:调用url:{},\n入参:{},\n返回:{},\n错误信息:{}", url, body, JSON.toJSONString(o), e.getMessage());
            String error = e.getMessage();
            throw new RuntimeException(error);
        }
        log.info("调用url:{},\n入参:{},\n返回:{}", url, body, JSON.toJSONString(o));
        return o;
    }


    /**
     * 查询案例
     * @return
     */
    @PostMapping("/query")
    public Object query() {
        String[] kind = new String[2];
        kind[0] = "02";
        Map<String, Object> map = new HashMap<>();
        map.put("page", "1");
        map.put("perPage", "1");
        map.put("orderBy", "");
        Map<String, Object> filters = new HashMap<>();
        filters.put("professionalKind", kind);
        filters.put("ctimeEnd", "2023-09-31 17:32:18");
        filters.put("ctimeStart", "2023-01-01 17:32:18");
        map.put("filters", filters);
        return queryOperate(INSPECTION_PLAN_QUERY, map);
    }

    /**
     * 新增测试
     * @return
     */
    @PostMapping("/saveTest")
    public Object saveTest(){
        Map<String, Object> map = new HashMap<>();
        map.put("completedDateTime","");
        map.put("containerId","73867B48-D9BE-492C-87CA-AA6812D98410-00005");
        map.put("createrId","F017B5E569335DA8E043621DE60A04B4");
        map.put("finishState","0");
        map.put("humidity","11");
        map.put("maintCrewId","16810251D14FC6DCE050E60A50273290");
        map.put("maintCrewName","变电运维一班");
        map.put("noFinishReason","");
        map.put("patrolCrewId","16810251D14FC6DCE050E60A50273290");
        map.put("patrolResult","未完成");
        map.put("patrolWorkId","8a80819c8e2e3e20018e303d66cf000e");
        map.put("patrolWorkTaskId","8a80819c8e2e3e20018e303e57ca0010");
        map.put("robotPatrolEndTime","2024-04-19 12:50:00");
        map.put("robotPatrolStartTime","2024-03-19 12:20:00");
        map.put("startedDateTime","");
        map.put("systemSource","无人机自主巡检微应用");
        map.put("systemSourceId","f6a37f99af0511ecb85bfa163ec6349c");
        map.put("temperature","0");
        map.put("weather","01");
        map.put("whetherUseApparatus","1");
        map.put("remark","56af264d8037483da511d5dfd70faf39,c4867f9c52934a028e170216ddd5a7cb");
        return addOrEditOrShowOperate(INSPECTION_RECORDS_SAVE, map);
    }




    public Map<String, Object> setDangerMap(List<Map<String, Object>> list) {

        Map<String, Object> oneMap = new HashMap<>();

        Map<String, Object> bodyMapOne = new HashMap<>();
        bodyMapOne.put("errors", "操作成功");

        bodyMapOne.put("result", list);
        bodyMapOne.put("pageSize", 1000);
        bodyMapOne.put("totalCount", 2);
        bodyMapOne.put("totalPage", 1);


        oneMap.put("body", bodyMapOne);

        Map<String, Object> headersOne = new HashMap<>();
        List<String> headersOneListContentType = new ArrayList<String>();
        headersOneListContentType.add("application/json;charset=UTF-8");
        headersOne.put("Content-Type", headersOneListContentType);
        List<String> headersOneListContentLength = new ArrayList<String>();
        headersOneListContentLength.add("1697");
        headersOne.put("Content-Length", headersOneListContentLength);
        List<String> headersOneListContentDate = new ArrayList<String>();
        headersOneListContentDate.add("Fri, 06 Jan 2023 11:07:34 GMT");
        headersOne.put("Date", headersOneListContentDate);
        oneMap.put("headers", headersOne);
        oneMap.put("statusCode", "OK");
        oneMap.put("statusCodeValue", 200);

        return oneMap;
    }

    @Override
    public void downloadFile(WMCenterUrlEnum urlEnum, Object data, HttpServletResponse response) {
        setMiddle();
        AccessTokenModel tokenObj = getToken(null);
        String token = tokenObj.getAccess_token();
        String url = middle.getMiddleHref() + urlEnum.getUrl();
        String body = JSON.toJSONString(data);
        log.info("调用参数：" + body);
        RestTemplate rest = new RestTemplate();
        response.setCharacterEncoding("utf-8");
        response.setContentType(MULTIPART_FORM_DATA_VALUE);
        HttpHeaders header = new HttpHeaders();
        header.add("x-token", token);
        header.add(HttpHeaders.CONTENT_TYPE, APPLICATION_JSON_VALUE);
        HttpEntity<String> entity = new HttpEntity<>(body, header);
        try {
            // 响应类型不支持InputStream类型，使用Resource或byte[]接收三方文件服务返回的文件字节流
            org.springframework.core.io.Resource apiResult = rest.postForObject(url, entity,
                    org.springframework.core.io.Resource.class);
            InputStream inputStream = apiResult.getInputStream();
            BufferedOutputStream out = FileUtil.getOutputStream("D:/test.jpeg");
            long copySize = IoUtil.copy(inputStream, out, IoUtil.DEFAULT_BUFFER_SIZE);
            IoUtil.close(inputStream);
            IoUtil.close(out);
        } catch (RestClientException e) {
            log.error("调用异常:调用url:{},\n入参:{},\n错误信息:{}", url, body, SystemUtils.getError(e));
            String error = SystemUtils.getError(e);
            throw new RuntimeException(error);
        } catch (IOException e) {
            log.error(e.getMessage());;
        }
    }

}
