package com.sptg.third.biz.qinlin.util;

import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.URLUtil;
import cn.hutool.json.JSONUtil;
import com.github.tobato.fastdfs.domain.StorePath;
import com.github.tobato.fastdfs.service.FastFileStorageClient;
import com.sptg.common.core.constant.OperationConstant;
import com.sptg.common.core.util.Base64DecodeMultipartFileUtils;
import com.sptg.common.core.util.JsonUtils;
import com.sptg.third.api.beans.ApiResultBean;
import com.sptg.third.api.beans.PageData;
import com.sptg.third.api.contants.UrlContants;
import com.sptg.third.api.entity.qinlin.*;
import com.sptg.third.biz.qinlin.conf.QinLinConfig;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.net.URI;
import java.net.URL;
import java.util.*;


/**
 * @author zwx
 * @create 2020/12/16 1:52
 */
@Slf4j
public class QinLinHttpUtil {
    /**
     *  新增用户
     *   新增用户，对接方系统传入userId作为用户的唯⼀标识；可在新增用户时同时传入deviceIds，此时将会在新增用户时向设备下发权限；userId若在亲邻系统中存在，则做更新处理；
     * @return
     */
    public static ApiResultBean addUser(QLinUser qLinUser, QinLinConfig qinLinConfig){
        Long timestamp = System.currentTimeMillis();
        String body = JSONUtil.toJsonStr(qLinUser);
        QinLinSignUtil.Signing sign = QinLinSignUtil.Signing.builder()
                .version(qinLinConfig.getVersion())
                .appid(qinLinConfig.getAppId())
                .secret(qinLinConfig.getAppSecret())
                .nonce(9999).timestamp(timestamp).body(body).build();
        String signStr = QinLinSignUtil.generateSign(sign);
        HttpHeaders headers = createHttpHeaders(sign, signStr);
        RestTemplate restTemplate = new RestTemplate();
        String url = qinLinConfig.getApiHost() + UrlContants.QinLin.ADD_USER;
        System.out.println("亲邻添加住户URL:" + url);
        ResponseEntity<ApiResultBean> response = null;
        HttpEntity<String> requestEntity = new HttpEntity<>(body, headers);
        URI uri = URI.create(url);
        ParameterizedTypeReference<ApiResultBean> reference = new ParameterizedTypeReference<ApiResultBean>() {};
        try{
            response = restTemplate.exchange(uri, HttpMethod.POST, requestEntity, reference);
        }catch (Exception e){
            e.printStackTrace();
        }

        return response.getBody();
    }

    /**
     *  删除用户
     *  删除用户信息及用户所有的设备权限
     * @return
     */
    public static ApiResultBean deleteUser(QLinUser qLinUser, QinLinConfig qinLinConfig){
        Long timestamp = System.currentTimeMillis();
        String body = JSONUtil.toJsonStr(qLinUser);
        QinLinSignUtil.Signing sign = QinLinSignUtil.Signing.builder()
                .version(qinLinConfig.getVersion())
                .appid(qinLinConfig.getAppId())
                .secret(qinLinConfig.getAppSecret())
                .nonce(9999).timestamp(timestamp).body(body).build();
        String signStr = QinLinSignUtil.generateSign(sign);
        HttpHeaders headers = createHttpHeaders(sign, signStr);
        RestTemplate restTemplate = new RestTemplate();
        String url = qinLinConfig.getApiHost() + UrlContants.QinLin.DELETE_USER;
        ResponseEntity<ApiResultBean> response = null;
        HttpEntity<String> requestEntity = new HttpEntity<>(body, headers);
        URI uri = URI.create(url);
        ParameterizedTypeReference<ApiResultBean> reference = new ParameterizedTypeReference<ApiResultBean>() {};
        response = restTemplate.exchange(uri, HttpMethod.POST, requestEntity, reference);
        return response.getBody();
    }

    /**
     *  删除用户权限
     *  删除用户指定设备的权限，用户信息保留
     * @return
     */
    public static ApiResultBean deleteUserPermission(QLinUserDevice qLinUserDevice, QinLinConfig qinLinConfig){
        String body = JSONUtil.toJsonStr(qLinUserDevice);
        Long timestamp = System.currentTimeMillis();
        QinLinSignUtil.Signing sign = QinLinSignUtil.Signing.builder()
                .version(qinLinConfig.getVersion())
                .appid(qinLinConfig.getAppId())
                .secret(qinLinConfig.getAppSecret())
                .nonce(9999).timestamp(timestamp).body(body).build();
        String signStr = QinLinSignUtil.generateSign(sign);
        HttpHeaders headers = createHttpHeaders(sign, signStr);
        RestTemplate restTemplate = new RestTemplate();
        String url = qinLinConfig.getApiHost() + UrlContants.QinLin.DELETE_USER_PERMISSION;
        ResponseEntity<ApiResultBean> response = null;
        HttpEntity<String> requestEntity = new HttpEntity<>(body, headers);
        URI uri = URI.create(url);
        ParameterizedTypeReference<ApiResultBean> reference = new ParameterizedTypeReference<ApiResultBean>() {};
        response = restTemplate.exchange(uri, HttpMethod.POST, requestEntity, reference);
        return response.getBody();
    }

    /**
     *  远程开门
     *  删除设备及用户在该设备上的权限
     * @return
     */
    public static ApiResultBean remoteOpenDoor(QLinUserDevice qLinUserDevice, QinLinConfig qinLinConfig){
        String body = JSONUtil.toJsonStr(qLinUserDevice);
        Long timestamp = System.currentTimeMillis();
        QinLinSignUtil.Signing sign = QinLinSignUtil.Signing.builder()
                .version(qinLinConfig.getVersion())
                .appid(qinLinConfig.getAppId())
                .secret(qinLinConfig.getAppSecret())
                .nonce(9999).timestamp(timestamp).body(body).build();
        String signStr = QinLinSignUtil.generateSign(sign);
        HttpHeaders headers = createHttpHeaders(sign, signStr);
        RestTemplate restTemplate = new RestTemplate();
        String url = qinLinConfig.getApiHost() + UrlContants.QinLin.REMOTE_DEVICE_OPEN_DOOR;
        ResponseEntity<ApiResultBean> response = null;
        HttpEntity<String> requestEntity = new HttpEntity<>(body, headers);
        URI uri = URI.create(url);
        ParameterizedTypeReference<ApiResultBean> reference = new ParameterizedTypeReference<ApiResultBean>() {};
        response = restTemplate.exchange(uri, HttpMethod.POST, requestEntity, reference);
        return response.getBody();
    }

    /**
     *  查询用户通行记录
     * @return
     */
    public static ApiResultBean<List<QLinOpenRecord>> getLogs(QLinQuery qLinQuery, QinLinConfig qinLinConfig, FastFileStorageClient fastFileStorageClient){
        List<QLinOpenRecord> qLinOpenRecordList = new ArrayList<>();
        ApiResultBean<List<QLinOpenRecord>> resultBean = new ApiResultBean<>();
        String message = null;
        Integer code = 0;
        String body = JSONUtil.toJsonStr(qLinQuery);
        Long timestamp = System.currentTimeMillis();
        QinLinSignUtil.Signing sign = QinLinSignUtil.Signing.builder()
                .version(qinLinConfig.getVersion())
                .appid(qinLinConfig.getAppId())
                .secret(qinLinConfig.getAppSecret())
                .nonce(9999).timestamp(timestamp).body(body).build();
        String signStr = QinLinSignUtil.generateSign(sign);
        HttpHeaders headers = createHttpHeaders(sign, signStr);
        RestTemplate restTemplate = new RestTemplate();
        String url = qinLinConfig.getApiHost() + UrlContants.QinLin.GET_LOGS;
        ResponseEntity<ApiResultBean<PageData<QLinOpenRecord>>> response = null;
        HttpEntity<String> requestEntity = new HttpEntity<>(body, headers);
        URI uri = URI.create(url);
        ParameterizedTypeReference<ApiResultBean<PageData<QLinOpenRecord>>> reference = new ParameterizedTypeReference<ApiResultBean<PageData<QLinOpenRecord>>>() {};
        response = restTemplate.exchange(uri, HttpMethod.POST, requestEntity, reference);
        ApiResultBean<PageData<QLinOpenRecord>> apiResultBean = response.getBody();
        Boolean success = apiResultBean.getSuccess();
        log.error("======================开门记录请求地址===============");
        log.error(url);
        if(success){
            PageData<QLinOpenRecord> pageData = apiResultBean.getData();
            List<QLinOpenRecord> list = pageData.getList();
            list.forEach(data ->{
                log.error("=============亲邻开门日志================");
                log.error(JsonUtils.objectToJson(data));
                log.error(JsonUtils.objectToJson(qLinQuery));
                if(qLinQuery.getDeviceId().equals(data.getDeviceId())){
                    String openType = data.getOpenType();
                    if(openType.equals(OperationConstant.ONE + "")){
                        //获取人脸图片
                        if(StringUtils.isNotBlank(data.getFaceUrl())){
                            ApiResultBean<String> faceResult = getLogsFaceUrl(data.getFaceUrl(), qinLinConfig);
                            String realFaceUrl = faceResult.getData();
                            if(StringUtils.isNotBlank(realFaceUrl)){
                                URL faceUrl = URLUtil.toUrlForHttp(realFaceUrl);
                                try{
                                    InputStream stream = URLUtil.getStream(faceUrl);
                                    byte[] bytes = IoUtil.readBytes(stream);
                                    String base64 = Base64.getEncoder().encodeToString(bytes);
                                    //图片上传
                                    String groupUrl = uploadFace(base64, fastFileStorageClient);
                                    data.setRealFaceUrl(groupUrl);
                                }catch (Exception e){
                                    data.setRealFaceUrl(realFaceUrl);
                                    e.printStackTrace();
                                }
                            }
                        }
                    }
                }
            });
            qLinOpenRecordList.addAll(list);
        }else{
            code = apiResultBean.getCode();
            message = apiResultBean.getMessage();
        }
        resultBean.setData(qLinOpenRecordList);
        resultBean.setMessage(message);
        resultBean.setCode(code);
        return resultBean;
    }

    public static ApiResultBean getLogsFaceUrl(String faceKey, QinLinConfig qinLinConfig){
        QLinUserDevice qLinUserDevice = new QLinUserDevice();
        String body = JSONUtil.toJsonStr(qLinUserDevice);
        Long timestamp = System.currentTimeMillis();
        QinLinSignUtil.Signing sign = QinLinSignUtil.Signing.builder()
                .version(qinLinConfig.getVersion())
                .appid(qinLinConfig.getAppId())
                .secret(qinLinConfig.getAppSecret())
                .nonce(9999).timestamp(timestamp).body(body).build();
        String signStr = QinLinSignUtil.generateSign(sign);
        HttpHeaders headers = createHttpHeaders(sign, signStr);
        RestTemplate restTemplate = new RestTemplate();
        String url = qinLinConfig.getApiHost() + UrlContants.QinLin.GET_LOGS_USER_FACE_URL + "?faceKey=" + faceKey + ".jpg";
        System.out.println("url  " + url);
        ResponseEntity<ApiResultBean> response = null;
        HttpEntity<String> requestEntity = new HttpEntity<>(null, headers);
        URI uri = URI.create(url);
        ParameterizedTypeReference<ApiResultBean> reference = new ParameterizedTypeReference<ApiResultBean>() {};
        response = restTemplate.exchange(uri, HttpMethod.POST, requestEntity, reference);
        return response.getBody();
    }

    /**
     *  新增小区
     * @return
     */
    public static ApiResultBean<Long> addCommunity(QLinCommunityDevices qLinCommunityDevices, QinLinConfig qinLinConfig){
        QLinUserDevice qLinUserDevice = new QLinUserDevice();
        String body = JSONUtil.toJsonStr(qLinUserDevice);
        Long timestamp = System.currentTimeMillis();
        QinLinSignUtil.Signing sign = QinLinSignUtil.Signing.builder()
                .version(qinLinConfig.getVersion())
                .appid(qinLinConfig.getAppId())
                .secret(qinLinConfig.getAppSecret())
                .nonce(9999).timestamp(timestamp).body(body).build();
        String signStr = QinLinSignUtil.generateSign(sign);
        HttpHeaders headers = createHttpHeaders(sign, signStr);
        headers.remove(HttpHeaders.CONTENT_TYPE);
        headers.add(HttpHeaders.CONTENT_TYPE, "application/x-www-form-urlencoded");
        RestTemplate restTemplate = new RestTemplate();
        String url = qinLinConfig.getApiHost() + UrlContants.QinLin.ADD_COMMUNITY + "?communityName=" + qLinCommunityDevices.getCommunityName();
        ResponseEntity<ApiResultBean> response = null;
        HttpEntity<String> requestEntity = new HttpEntity<>(null, headers);
        URI uri = URI.create(url);
        ParameterizedTypeReference<ApiResultBean<Long>> reference = new ParameterizedTypeReference<ApiResultBean<Long>>() {};
        response = restTemplate.postForEntity(url, requestEntity, ApiResultBean.class);
        return response.getBody();
    }

    /**
     *  新增设备
     * @return
     */
    public static ApiResultBean addDevices(QLinCommunityDevices qLinCommunityDevices, QinLinConfig qinLinConfig){
        String body = JSONUtil.toJsonStr(qLinCommunityDevices);
        Long timestamp = System.currentTimeMillis();
        QinLinSignUtil.Signing sign = QinLinSignUtil.Signing.builder()
                .version(qinLinConfig.getVersion())
                .appid(qinLinConfig.getAppId())
                .secret(qinLinConfig.getAppSecret())
                .nonce(9999).timestamp(timestamp).body(body).build();
        String signStr = QinLinSignUtil.generateSign(sign);
        HttpHeaders headers = createHttpHeaders(sign, signStr);
        RestTemplate restTemplate = new RestTemplate();
        String url = qinLinConfig.getApiHost() + UrlContants.QinLin.ADD_DEVICES;
        ResponseEntity<ApiResultBean> response = null;
        HttpEntity<String> requestEntity = new HttpEntity<>(body, headers);
        URI uri = URI.create(url);
        ParameterizedTypeReference<ApiResultBean> reference = new ParameterizedTypeReference<ApiResultBean>() {};
        response = restTemplate.exchange(uri, HttpMethod.POST, requestEntity, reference);
        return response.getBody();
    }

    /**
     * 构建stringSignTemp
     * @param params
     * @return
     */
    private String createLinkString(Map<String, String> params){
        List<String> keys = new ArrayList(params.keySet());
        Collections.sort(keys);
        StringBuilder content = new StringBuilder();
        for(int i = 0; i < keys.size(); ++i) {
            String key = keys.get(i);
            String value = params.get(key);
            if (i == keys.size() - 1) {
                content.append(key).append("=").append(value);
            } else {
                content.append(key).append("=").append(value).append("&");
            }
        }
        return content.toString();
    }

    public static HttpHeaders createHttpHeaders(QinLinSignUtil.Signing sign, String signStr){
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.add(HttpHeaders.CONTENT_TYPE, "application/json");
        httpHeaders.add("version", sign.getVersion());
        httpHeaders.add("appid", sign.getAppid());
        httpHeaders.add("nonce", sign.getNonce() + "");
        httpHeaders.add("timestamp", sign.getTimestamp() + "");
        httpHeaders.add("sign", signStr);
        return httpHeaders;
    }

    //上传人脸
    public static String uploadFace(String face_image_base64, FastFileStorageClient fastFileStorageClient){
        if(StringUtils.isNotBlank(face_image_base64)){
            MultipartFile multipartFile  = Base64DecodeMultipartFileUtils.base64ToMultipart(Base64DecodeMultipartFileUtils.imageFormatToPng("data:image/png;base64," + face_image_base64));
            //图片上传
            StorePath storePath = null;
            try {
                storePath = fastFileStorageClient.uploadFile(
                        multipartFile.getInputStream(),multipartFile.getSize(),
                        FilenameUtils.getExtension(multipartFile.getOriginalFilename()),null);
            } catch (IOException e) {
                return null;
            }
            return storePath.getFullPath();
        }else{
            return null;
        }
    }
}
