package org.springblade.openinterface.facedevice.qinlin.util;

import cn.hutool.core.io.IoUtil;
import cn.hutool.core.lang.UUID;
import cn.hutool.core.util.URLUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import io.minio.MinioClient;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springblade.config.OssConfig;
import org.springblade.config.QinLinConfig;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.utils.StringUtil;
import org.springblade.openinterface.facedevice.qinlin.beans.PageData;
import org.springblade.openinterface.facedevice.qinlin.beans.QinLinApiResultBean;
import org.springblade.openinterface.facedevice.qinlin.contants.QinLinUrlConstants;
import org.springblade.openinterface.facedevice.qinlin.vo.*;
import org.springframework.beans.factory.annotation.Autowired;
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.stereotype.Component;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.MultipartFile;

import java.io.InputStream;
import java.net.URI;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.*;


/**
 * @author zwx
 * @create 2020/12/16 1:52
 */
@Slf4j
@Component
public class QinLinHttpUtil {

	@Autowired
	private OssConfig ossConfig;
	@Autowired
	private QinLinConfig qinLinConfig;

    /**
     *  新增用户
     *   新增用户，对接方系统传入userId作为用户的唯⼀标识；可在新增用户时同时传入deviceIds，此时将会在新增用户时向设备下发权限；userId若在亲邻系统中存在，则做更新处理；
     * @return
     */
    public QinLinApiResultBean addUser(QLinUser qLinUser){
		String expires = qLinUser.getExpires();
		if(StringUtil.isBlank(expires)){
			Date today = new Date();
			Calendar cd = Calendar.getInstance();
			cd.setTime(today);
			cd.add(Calendar.YEAR, 10);
			Date expireDate = cd.getTime();
			SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
			qLinUser.setExpires(sdf.format(expireDate));
		}
		Long timestamp = System.currentTimeMillis();
        String body = JSONUtil.toJsonStr(qLinUser);
        log.info("body >>>>>>>>>> " + body);
        QinLinSignUtil.Signing sign = QinLinSignUtil.Signing.builder().version(qinLinConfig.getVersion())
                .nonce(9999).timestamp(timestamp).appid(qinLinConfig.getAppId()).secret(qinLinConfig.getAppSecret()).body(body).build();
        String signStr = QinLinSignUtil.generateSign(sign);
        HttpHeaders headers = createHttpHeaders(sign, signStr);
        RestTemplate restTemplate = new RestTemplate();
        String url = qinLinConfig.getApiHost() + QinLinUrlConstants.ADD_USER;
        ResponseEntity<QinLinApiResultBean> response = null;
        HttpEntity<String> requestEntity = new HttpEntity<>(body, headers);
        URI uri = URI.create(url);
        ParameterizedTypeReference<QinLinApiResultBean> reference = new ParameterizedTypeReference<QinLinApiResultBean>() {};
        response = restTemplate.exchange(uri, HttpMethod.POST, requestEntity, reference);
        return response.getBody();
    }

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

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

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

    /**
     *  查询用户通行记录
     * @return
     */
    public QinLinApiResultBean<List<QLinOpenRecord>> getLogs(QLinQuery qLinQuery){
        List<QLinOpenRecord> qLinOpenRecordList = new ArrayList<>();
		QinLinApiResultBean<List<QLinOpenRecord>> resultBean = new QinLinApiResultBean<>();
        String message = null;
        Integer code = 0;
        String body = JSONUtil.toJsonStr(qLinQuery);
        log.info("getOpenDoorLogs body >>>>>>>>>> " + body);
        Long timestamp = System.currentTimeMillis();
        QinLinSignUtil.Signing sign = QinLinSignUtil.Signing.builder().version(qinLinConfig.getVersion())
                .nonce(9999).timestamp(timestamp).appid(qinLinConfig.getAppId()).secret(qinLinConfig.getAppSecret()).body(body).build();
        String signStr = QinLinSignUtil.generateSign(sign);
        HttpHeaders headers = createHttpHeaders(sign, signStr);
        RestTemplate restTemplate = new RestTemplate();
        String url = qinLinConfig.getApiHost() + QinLinUrlConstants.GET_LOGS;
//            String url = qinLinConfig.getApiHost() + UrlContants.QinLin.GET_LOGS;
        ResponseEntity<QinLinApiResultBean<PageData<QLinOpenRecord>>> response = null;
        HttpEntity<String> requestEntity = new HttpEntity<>(body, headers);
        URI uri = URI.create(url);
        ParameterizedTypeReference<QinLinApiResultBean<PageData<QLinOpenRecord>>> reference = new ParameterizedTypeReference<QinLinApiResultBean<PageData<QLinOpenRecord>>>() {};
        response = restTemplate.exchange(uri, HttpMethod.POST, requestEntity, reference);
		QinLinApiResultBean<PageData<QLinOpenRecord>> apiResultBean = response.getBody();
		log.info("================开门纪录============");
		log.info(JSON.toJSONString(apiResultBean));
        Boolean success = apiResultBean.getSuccess();
        if(success){
            PageData<QLinOpenRecord> pageData = apiResultBean.getData();
            List<QLinOpenRecord> list = pageData.getList();
            for (int i = 0; i < list.size(); i++){
				QLinOpenRecord data = list.get(i);
				if(qLinQuery.getDeviceId().contains(data.getDeviceId())){ //返回的记录里面是否包含在本次请求的设备
					String openType = data.getOpenType();
					if(openType.equals("1")){
						try{
							//获取人脸图片
							if(StringUtils.isNotBlank(data.getFaceUrl())){
								QinLinApiResultBean<String> faceResult = this.getLogsFaceUrl(data.getFaceUrl());
								String realFaceUrl = faceResult.getData();
								if(StringUtils.isNotBlank(realFaceUrl)){
									URL faceUrl = URLUtil.toUrlForHttp(realFaceUrl);
									try{
										InputStream stream = (InputStream) URLUtil.getStream(faceUrl);
										byte[] bytes = IoUtil.readBytes(stream);
										String base64 = "data:image/png;base64," + Base64.getEncoder().encodeToString(bytes);
										//图片上传
										MultipartFile multipartFile = BASE64DecodedMultipartFile.base64ToMultipart(base64);
										R<String> stringR = this.putFile(multipartFile);
										data.setRealFaceUrl(stringR.getData());
									}catch (Exception e){
										data.setRealFaceUrl(realFaceUrl);
										e.printStackTrace();
									}
								}
							}else{
								log.info("=========================开门记录返回人脸图片为null=======================");
							}
						}catch (Exception e){
							e.printStackTrace();
						}
					}
					qLinOpenRecordList.add(data);
				}
			}
        }else{
            code = apiResultBean.getCode();
            message = apiResultBean.getMessage();
        }
        resultBean.setData(qLinOpenRecordList);
        resultBean.setMessage(message);
        resultBean.setCode(code);
        return resultBean;
    }

    @RequestMapping("/open/face/v1/openlog/getUserFaceUrl/{faceKey}")
    public QinLinApiResultBean getLogsFaceUrl(@PathVariable(value = "faceKey") String faceKey){
        QLinUserDevice qLinUserDevice = new QLinUserDevice();
        String body = JSONUtil.toJsonStr(qLinUserDevice);
        System.out.println("body   " + body);
        Long timestamp = System.currentTimeMillis();
        QinLinSignUtil.Signing sign = QinLinSignUtil.Signing.builder()
			.version(qinLinConfig.getVersion()).nonce(9999).timestamp(timestamp)
			.appid(qinLinConfig.getAppId()).secret(qinLinConfig.getAppSecret()).body(body).build();
        String signStr = QinLinSignUtil.generateSign(sign);
        HttpHeaders headers = createHttpHeaders(sign, signStr);
        RestTemplate restTemplate = new RestTemplate();
        String url = qinLinConfig.getApiHost() + QinLinUrlConstants.GET_LOGS_USER_FACE_URL + "?faceKey=" + faceKey + ".jpg";
        System.out.println("url  " + url);
        ResponseEntity<QinLinApiResultBean> response = null;
        HttpEntity<String> requestEntity = new HttpEntity<>(null, headers);
        URI uri = URI.create(url);
        ParameterizedTypeReference<QinLinApiResultBean> reference = new ParameterizedTypeReference<QinLinApiResultBean>() {};
        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 R<String> putFile(@RequestParam MultipartFile file){
		String fileName = UUID.fastUUID() + "-" + file.getOriginalFilename();
		String endpoint = ossConfig.getEndpoint();
		String accessKey = ossConfig.getAccessKey();
		String secretKey = ossConfig.getSecretKey();
		String bucketName = ossConfig.getBucketName();
		String returnPath = ossConfig.getReturnPath();
		try {
			// 使用MinIO服务的URL，端口，Access key和Secret key创建一个MinioClient对象
			MinioClient minioClient = new MinioClient(endpoint, accessKey, secretKey);
			// 检查存储桶是否已经存在
			boolean isExist = minioClient.bucketExists(bucketName);
			if(isExist) {
				System.out.println(bucketName + " already exists.");
			} else {

				minioClient.makeBucket(bucketName);
			}
			// 使用putObject上传一个文件到存储桶中。
			minioClient.putObject(bucketName,fileName, file.getInputStream(),file.getInputStream().available(),"application/octet-stream");
		} catch(Exception e) {
			System.out.println("Error occurred: " + e);
			return R.fail("fail");
		}
		return R.success((returnPath+fileName).trim());
	}

	/**
	 *  新增小区
	 * @return
	 */
	public QinLinApiResultBean<Long> addCommunity(QLinCommunityDevices qLinCommunityDevices){
		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() + QinLinUrlConstants.REGISTER_COMMUNITY + "?communityName=" + qLinCommunityDevices.getCommunityName();
		ResponseEntity<QinLinApiResultBean> response = null;
		HttpEntity<String> requestEntity = new HttpEntity<>(null, headers);
		response = restTemplate.postForEntity(url, requestEntity, QinLinApiResultBean.class);
		return response.getBody();
	}

	/**
	 *  新增设备
	 * @return
	 */
	public QinLinApiResultBean addDevices(QLinCommunityDevices qLinCommunityDevices){
		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 = QinLinHttpUtil.createHttpHeaders(sign, signStr);
		RestTemplate restTemplate = new RestTemplate();
		String url = qinLinConfig.getApiHost() + QinLinUrlConstants.REGISTER_DEVICE;
		ResponseEntity<QinLinApiResultBean> response = null;
		HttpEntity<String> requestEntity = new HttpEntity<>(body, headers);
		URI uri = URI.create(url);
		ParameterizedTypeReference<QinLinApiResultBean> reference = new ParameterizedTypeReference<QinLinApiResultBean>() {};
		response = restTemplate.exchange(uri, HttpMethod.POST, requestEntity, reference);
		return response.getBody();
	}
}
