package thyyxxk.webserver.utils;

import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Base64;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.http.HttpHeaders;
import org.springframework.stereotype.Component;
import thyyxxk.webserver.config.exception.ExceptionEnum;
import thyyxxk.webserver.constants.sidicts.SiFunction;
import thyyxxk.webserver.entity.ResultVo;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @description: 新医保交易工具类
 * @author: DingJie
 * @create: 2021-05-14 16:41:21
 **/
@Component
@Slf4j
public class SiUtil {
    private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
    private static int serial = 1000;
    private static final int MIN_VAL = 1000;
    private static final int MAX_VAL = 9999;
    public static final String INSTITUTION_AREA = "430105";
    public static final String INSTITUTION_ID = "H43010500370";
    public static final String INSTITUTION_NAME = "长沙泰和医院";
    private static String apiAccessKey;
    private static String apiSecretKey;

    public static final String API_VERSION = "1.0.0";

    @Autowired
    public SiUtil(Environment environment) {
        apiAccessKey = environment.getProperty("si-access-key");
        apiSecretKey = environment.getProperty("si-secret-key");
    }

    public static String getInstitutionArea(String insureArea) {
        return insureArea.startsWith("4301") ? INSTITUTION_AREA : "439900";
    }

    public static synchronized String makeMsgId() {
        serial += 1;
        if (serial > MAX_VAL) {
            serial = MIN_VAL;
        }
        return INSTITUTION_ID + sdf.format(new Date()) + serial;
    }

    public static Map<String, String> getSiHeaderMap(SiFunction function) {
        Map<String, String> headers = new HashMap<>();
        String timestamp = String.valueOf(System.currentTimeMillis());
        String signature = getSignature(timestamp, function.getCode());
//        headers.put("_api_access_key", apiAccessKey);
//        headers.put("_api_secreKey", apiSecretKey);
//        headers.put("_api_name", function.getCode());
//        headers.put("_api_version", API_VERSION);
//        headers.put("_api_timestamp", timestamp);
//        headers.put("_api_signature", signature);
        headers.put("apiAccessKey", apiAccessKey);
        headers.put("apiSecreKey", apiSecretKey);
        headers.put("apiName", function.getCode());
        headers.put("apiVersion", API_VERSION);
        headers.put("apiTimestamp", timestamp);
        headers.put("apiSignature", signature);
        return headers;
    }

    public static HttpHeaders getHttpHeaders(SiFunction function) {
        String timestamp = String.valueOf(System.currentTimeMillis());
        String signature = getSignature(timestamp, function.getCode());
        HttpHeaders headers = new HttpHeaders();
//        headers.add("_api_access_key", apiAccessKey);
//        headers.add("_api_secreKey", apiSecretKey);
//        headers.add("_api_name", function.getCode());
//        headers.add("_api_version", API_VERSION);
//        headers.add("_api_timestamp", timestamp);
//        headers.add("_api_signature", signature);
        headers.add("apiAccessKey", apiAccessKey);
        headers.add("apiSecreKey", apiSecretKey);
        headers.add("apiName", function.getCode());
        headers.add("apiVersion", API_VERSION);
        headers.add("apiTimestamp", timestamp);
        headers.add("apiSignature", signature);
        return headers;
    }

    public static String getSignature(String timestamp, String function) {
        String source =
                "_api_access_key=" + apiAccessKey +
                        "&_api_name=" + function +
                        "&_api_timestamp=" + timestamp +
                        "&_api_version=" + API_VERSION;
        return hmacSha1(source);
    }

    private static String hmacSha1(String src) {
        byte[] result = null;
        try {
            SecretKeySpec signInKey = new SecretKeySpec(apiSecretKey.getBytes(), "HmacSHA1");
            Mac mac = Mac.getInstance("HmacSHA1");
            mac.init(signInKey);
            byte[] rawHmac = mac.doFinal(src.getBytes());
            result = Base64.encodeBase64(rawHmac);
        } catch (Exception e) {
            log.error("HmacSHA1加密出错", e);
        }
        return null == result ? null : new String(result);
    }

    private static final String RESULT_CODE = "infcode";
    private static final String ERROR_MESSAGE = "err_msg";

    public static ResultVo<String> makeReturnWithoutOutput(JSONObject result, String message) {
        if (null == result) {
            return ResultVoUtil.fail(ExceptionEnum.NETWORK_ERROR);
        }
        if (result.getIntValue(RESULT_CODE) == 0) {
            return ResultVoUtil.success(message);
        }
        return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, result.getString(ERROR_MESSAGE));
    }


    public static Queue<String> readTxtFile(String path) {
        Queue<String> result = new LinkedList<>();
        try {
            File file = new File(path);
            InputStreamReader isr = new InputStreamReader(Files.newInputStream(file.toPath()), StandardCharsets.UTF_8);
            BufferedReader br = new BufferedReader(isr);
            String temp;
            while ((temp = br.readLine()) != null) {
                result.add(temp);
            }
        } catch (Exception e) {
            log.error("读取txt文件出错", e);
            return null;
        }
        return result;
    }

}
