package org.springblade.modules.nh.factory.ginlong;

import com.google.common.collect.Maps;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springblade.core.tool.utils.Base64Util;
import org.springblade.core.tool.utils.StringUtil;
import org.springblade.modules.nh.factory.ginlong.dto.alarmlist.GetAlarmListR;
import org.springblade.modules.nh.factory.ginlong.dto.alarmlist.GetAlarmListReq;
import org.springblade.modules.nh.factory.ginlong.dto.collectorlist.GetCollectorListR;
import org.springblade.modules.nh.factory.ginlong.dto.collectorlist.GetCollectorListResp;
import org.springblade.modules.nh.factory.ginlong.dto.inverterday.GetInverterDayR;
import org.springblade.modules.nh.factory.ginlong.dto.inverterday.GetInverterDayReq;
import org.springblade.modules.nh.factory.ginlong.dto.inverterdetaillist.GetInverterDetailListReq;
import org.springblade.modules.nh.factory.ginlong.dto.inverterdetaillist.GetInverterDetailR;
import org.springblade.modules.nh.factory.ginlong.dto.inverterlist.GetInverterListReq;
import org.springblade.modules.nh.factory.ginlong.dto.inverterlist.GetInverterListResp;
import org.springblade.modules.nh.factory.ginlong.dto.invertermonth.GetInverterMonthR;
import org.springblade.modules.nh.factory.ginlong.dto.invertermonth.GetInverterMonthReq;
import org.springblade.modules.nh.factory.ginlong.dto.stationday.GetStationDayR;
import org.springblade.modules.nh.factory.ginlong.dto.stationday.GetStationDayReq;
import org.springblade.modules.nh.factory.ginlong.dto.stationdayenergylist.GetStationDayEnergyListR;
import org.springblade.modules.nh.factory.ginlong.dto.stationdayenergylist.GetStationDayEnergyListReq;
import org.springblade.modules.nh.factory.ginlong.dto.stationmonth.GetStationMonthR;
import org.springblade.modules.nh.factory.ginlong.dto.stationmonth.GetStationMonthReq;
import org.springblade.modules.nh.factory.ginlong.dto.stationyear.GetStationYearR;
import org.springblade.modules.nh.factory.ginlong.dto.stationyear.GetStationYearReq;
import org.springblade.modules.nh.factory.ginlong.dto.userstationlist.GetStationListReq;
import org.springblade.modules.nh.factory.ginlong.dto.userstationlist.GetStationListResp;
import org.springblade.modules.nh.factory.ginlong.dto.userstationlist.GetStationR;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.stereotype.Service;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.util.*;

@Service
public class GinlongApi  {

    private static final String apiUrl = "https://api.ginlong.com:13333/";
    private static final Logger log = LoggerFactory.getLogger(GinlongApi.class);
    private static final String HMAC_SHA1_ALGORITHM = "HmacSHA1";

    @Autowired
    GinlongApiRestTemplate ginlongApiRestTemplate;

    public IRet<GetStationListResp> userStationList(GetStationListReq req) {
        String url = "https://api.ginlong.com:13333/v1/api/userStationList";
        return ginlongApiRestTemplate.postJson(req.getIndex(),url, req, new ParameterizedTypeReference<IRet<GetStationListResp>>() {
        });
    }

	public IRet<GetStationR> stationDetail(int index,String outStationId) {
		Map<String,String> req = Maps.newHashMap();
		req.put("id",outStationId);
		String url = "https://api.ginlong.com:13333/v1/api/stationDetail";
		return ginlongApiRestTemplate.postJson(index,url, req, new ParameterizedTypeReference<IRet<GetStationR>>() {
		});
	}

	public IRet<GetInverterDetailR> inverterDetail(int index,String outInverterId,String sn) {
		Map<String,String> req = Maps.newHashMap();
		if(StringUtil.isNotBlank(outInverterId)){
			req.put("id",outInverterId);
		}
		if(StringUtil.isNotBlank(sn)){
			req.put("sn",sn);
		}
		String url = "https://api.ginlong.com:13333/v1/api/inverterDetail";
		return ginlongApiRestTemplate.postJson(index,url, req, new ParameterizedTypeReference<IRet<GetInverterDetailR>>() {
		});
	}

    public IRet<GetInverterListResp> inverterList(GetInverterListReq req) throws IOException {
        String url = "https://api.ginlong.com:13333/v1/api/inverterList";
        return ginlongApiRestTemplate.postJson(req.getIndex(),url, req, new ParameterizedTypeReference<IRet<GetInverterListResp>>() {
        });
    }

    /**
     * 逆变器日实时数据
     */
    public IRet<List<GetInverterDayR>> inverterDay(GetInverterDayReq req) throws IOException {
        String url = "https://api.ginlong.com:13333/v1/api/inverterDay";
        return ginlongApiRestTemplate.postJson(req.getIndex(),url, req, new ParameterizedTypeReference<IRet<List<GetInverterDayR>>>() {
        });
    }

    /**
     * 获取多个电站某日的实时数据
     */
    public IRet<Page<GetStationDayEnergyListR>> stationDayEnergyList(GetStationDayEnergyListReq req) throws IOException {
        String url = "https://api.ginlong.com:13333/v1/api/stationDayEnergyList";
        return ginlongApiRestTemplate.postJson(req.getIndex(),url, req, new ParameterizedTypeReference<IRet<Page<GetStationDayEnergyListR>>>() {
        });
    }

    /**
     * 获取账号下设备报警列表
     */
    public IRet<Page<GetAlarmListR>> alarmList(GetAlarmListReq req) throws IOException {
        String url = "https://api.ginlong.com:13333/v1/api/alarmList";
        return ginlongApiRestTemplate.postJson(req.getIndex(),url, req, new ParameterizedTypeReference<IRet<Page<GetAlarmListR>>>() {
        });
    }

    /**
     * 获取单个电站某日的实时数据
     */
    public IRet<List<GetStationDayR>> stationDay(GetStationDayReq req) throws IOException {
        String url = "https://api.ginlong.com:13333/v1/api/stationDay";
        return ginlongApiRestTemplate.postJson(req.getIndex(),url, req, new ParameterizedTypeReference<IRet<List<GetStationDayR>>>() {
        });
    }

    /**
     * 获取单个电站某月的日数据
     */
    public IRet<List<GetStationMonthR>> stationMonth(GetStationMonthReq req) throws IOException {
        String url = "https://api.ginlong.com:13333/v1/api/stationMonth";
        return ginlongApiRestTemplate.postJson(req.getIndex(),url, req, new ParameterizedTypeReference<IRet<List<GetStationMonthR>>>() {
        });
    }

    /**
     * 获取单台逆变器某月的日数据
     */
    public IRet<List<GetInverterMonthR>> inverterMonth(GetInverterMonthReq req) throws IOException {
        String url = "https://api.ginlong.com:13333/v1/api/inverterMonth";
        return ginlongApiRestTemplate.postJson(req.getIndex(),url, req, new ParameterizedTypeReference<IRet<List<GetInverterMonthR>>>() {
        });
    }

    /**
     * 获取单个电站某年的月数据
     */
    public IRet<List<GetStationYearR>> stationYear(GetStationYearReq req) throws IOException {
        String url = "https://api.ginlong.com:13333/v1/api/stationYear";
        return ginlongApiRestTemplate.postJson(req.getIndex(),url, req, new ParameterizedTypeReference<IRet<List<GetStationYearR>>>() {
        });
    }

    /**
     * 逆变器详情列表
     */
    public IRet<Page<GetInverterDetailR>> inverterDetailList(GetInverterDetailListReq req) throws IOException {
        String url = "https://api.ginlong.com:13333/v1/api/inverterDetailList";
        return ginlongApiRestTemplate.postJson(req.getIndex(),url, req, new ParameterizedTypeReference<IRet<Page<GetInverterDetailR>>>() {
        });
    }

    /**
     * 获取账号下采集器列表
     */
    public IRet<GetCollectorListResp> collectorList(GetInverterDetailListReq req) throws IOException {
        String url = "https://api.ginlong.com:13333/v1/api/collectorList";
        return ginlongApiRestTemplate.postJson(req.getIndex(),url, req, new ParameterizedTypeReference<IRet<GetCollectorListResp>>() {
        });
    }

	public IRet<GetCollectorListR> collectorDetail(int index,String outDeviceId, String sn) throws IOException {
		Map<String,String> req = Maps.newHashMap();
		if(StringUtil.isNotBlank(outDeviceId)){
			req.put("id",outDeviceId);
		}
		if(StringUtil.isNotBlank(sn)){
			req.put("sn",sn);
		}
		String url = "https://api.ginlong.com:13333/v1/api/collectorDetail";
		return ginlongApiRestTemplate.postJson(index,url, req, new ParameterizedTypeReference<IRet<GetCollectorListR>>() {
		});
	}

    public static String getGMTTime() {
        Calendar cd = Calendar.getInstance();
        SimpleDateFormat sdf = new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss 'GMT'", Locale.US);
        sdf.setTimeZone(TimeZone.getTimeZone("GMT"));
        return sdf.format(cd.getTime());
    }

    public static byte[] genHMAC(String data, String key) {
        try {
            SecretKeySpec signinKey = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), HMAC_SHA1_ALGORITHM);
            Mac mac = Mac.getInstance(HMAC_SHA1_ALGORITHM);
            mac.init(signinKey);
            return mac.doFinal(data.getBytes());
        } catch (NoSuchAlgorithmException | InvalidKeyException e) {
            throw new RuntimeException(e);
        }
    }

    public static String getAuthorization(String contentMd5, String date, String url, String apiId, String apiSecret) {
        log.info("get authorization, content.md5: {}, date: {}, url: {}", contentMd5, date, url);
        StringBuilder sb = new StringBuilder();
        sb.append("POST\n");
        sb.append(contentMd5).append("\n");
        sb.append("application/json\n");
        sb.append(date).append("\n");
        sb.append(url.substring("https://api.ginlong.com:13333".length()));
        byte[] bytes = genHMAC(sb.toString(), apiSecret);
        return "API " + apiId + ":" + Base64Util.encodeToString(bytes);

    }

    public static String getDigest(String test) {
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            md.update(test.getBytes());
            byte[] b = md.digest();
            return Base64Util.encodeToString(b);
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException(e);
        }
    }

    public static void main(String[] args) {
        String url = "https://api.ginlong.com:13333/v1/api/userStationList";
        System.out.println(url.substring("https://api.ginlong.com:13333".length()));
    }

}
