package com.dxhy.core.util;

import cn.hutool.core.codec.Base64;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSONObject;
import com.dxhy.common.constant.CoreConstants;
import com.dxhy.common.constant.DbConstant;
import com.dxhy.common.datasource.config.DynamicContextHolder;
import com.dxhy.core.job.pojo.Authorize;
import com.dxhy.core.job.pojo.BaseQueJson;
import com.dxhy.core.job.pojo.BaseResJson;
import com.dxhy.core.job.pojo.GlobalInfo;
import lombok.extern.slf4j.Slf4j;

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

/**
 * @author Allen
 * @version 1.0.0
 * @ClassName Dqyjkdyutil.java
 * @Description 大企业接口调用工具
 * @createTime 2023年08月15日 17:40:00
 */
@Slf4j
public class Dqyjkdyutil {
    /**
     * @description  大企业接口调用统一方法
     * @author  Allen
     * @date    2023/8/15 17:48
     * @param
     * @return
    */
    public static BaseResJson call(Map<String,Object> httpLogMap, String interfaceCode, String aceId, String aceKey, Object invoiceSelectData) {
            BaseQueJson bqj = new BaseQueJson();
            // 请求通用头
            GlobalInfo globalInfo = new GlobalInfo();
            // 请求通用
            Authorize authorize = new Authorize();
            // 封装参数
            globalInfo.setAppId(CoreConstants.appId);
            globalInfo.setVersion(CoreConstants.version);
            String exchangeId = getDataExchangeId();
            globalInfo.setDataExchangeId(exchangeId);
            globalInfo.setInterfaceCode(interfaceCode);
            globalInfo.setEnterpriseCode(CoreConstants.enterpriseCode);
            authorize.setAppSecId(aceId);
            String base64Data = Base64.encode(JSONObject.toJSONString(invoiceSelectData));
            String appSec = makeAppSec(base64Data, exchangeId, interfaceCode, aceId, aceKey);
            authorize.setAppSec(appSec);
            bqj.setData(base64Data);
            bqj.setAuthorize(authorize);
            bqj.setGlobalInfo(globalInfo);
            String collectDataStr = JSONObject.toJSONString(bqj);
            log.info("url:" + CoreConstants.collectUrl);
            log.info("请求参数：" + collectDataStr);
            log.info("发送请求--");
            httpLogMap.put(CoreConstants.reqText, collectDataStr);
            // 得到返回报文，解析拿出返回的数量，累加用于判断数量
            httpLogMap.put(CoreConstants.reqDate, new Date());
            String responseJson = HttpUtil.post(CoreConstants.collectUrl, collectDataStr, 600000);
            httpLogMap.put(CoreConstants.resDate, new Date());
            log.info("返回参数:{}", responseJson);
            // 根据发票类型保存不同实体
            BaseResJson gatherData = JSONObject.parseObject(responseJson, BaseResJson.class);
            httpLogMap.put(CoreConstants.resText, responseJson);
            return gatherData;
    }
    /**
     * 获取时间戳
     *
     * @return String
     */
    public static String getDataExchangeId() {
        // enterpriseCode+8 位日期
        // (YYYYMMDD)+9 位序列号
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
        StringBuilder sb = new StringBuilder();
        Random rand = new Random();
        for (int i = 0; i < 9; i++) {
            sb.append(rand.nextInt(10));
        }
        String data = sb.toString();
        return CoreConstants.enterpriseCode + simpleDateFormat.format(new Date()) + data;
    }

    /**
     * @description  获取请求批次号
     * @author  Allen
     * @date    2023/12/7 15:14
    */
    public static String getBatchNo() {
        return UUID.randomUUID().toString().replaceAll("-", "");
    }



    /**
     * 获取开始时间
     * @param lastCollectTime 末次采集时间yyyyMMddHHmmss
     * @param firstCollectDate 默认采集开始日期，如果末次采集时间为空使用此时间
     *
     * @return 开始采集时间
     */
    public static String getBeginTime(String lastCollectTime, Date firstCollectDate) {
        //查询增值税发票归集上次请求时间
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
        if (lastCollectTime == null || "".equals(lastCollectTime)) {
            DynamicContextHolder.push(DbConstant.BASICS_READ);
            if (firstCollectDate!= null) {
                lastCollectTime = simpleDateFormat.format(firstCollectDate);
            } else {
                Calendar c2 = new GregorianCalendar();
                c2.set(Calendar.HOUR_OF_DAY, 0);
                c2.set(Calendar.MINUTE, 0);
                c2.set(Calendar.SECOND, 0);
                c2.set(Calendar.DAY_OF_MONTH, 1);
                lastCollectTime = simpleDateFormat.format(c2.getTime());
            }
        } else {
            // 避免防止漏票，提前两个小时
            try {
                Date date = simpleDateFormat.parse(lastCollectTime);
                Calendar cal = Calendar.getInstance();
                cal.setTime(date);
                cal.add(Calendar.HOUR_OF_DAY, -2);
                date = cal.getTime();
                lastCollectTime = simpleDateFormat.format(date);
            } catch (ParseException e) {
                log.debug("业务异常：{}",e);
            }
        }

        return lastCollectTime;
    }

    /**
     * 获取开始时间--针对归集。如果空，获取到操作时间的前60天
     * @param lastCollectTime 末次采集时间yyyyMMddHHmmss
     * @param firstCollectDate 默认采集开始日期，如果末次采集时间为空使用此时间
     *
     * @return 开始采集时间
     */
    public static String getBeginTimeGj(String lastCollectTime, Date firstCollectDate) {
        //查询增值税发票归集上次请求时间
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
        try {
            String twoMonthAgo = DateUtils.getDate(60)+"000000";
            if (lastCollectTime == null || "".equals(lastCollectTime)) {
                if (firstCollectDate!= null) {
                    //判断firstCollectDate时间和两个月前twoMonthAgo。如果小于，用两个月前，大于等于，用firstCollectDate
                    if(firstCollectDate.compareTo(DateUtils.strToDate(twoMonthAgo, "yyyyMMddHHmmss"))<0){
                        lastCollectTime = twoMonthAgo;
                    }else{
                        lastCollectTime = simpleDateFormat.format(firstCollectDate);
                    }
                } else {
                    //空就直接用两个月前
                    lastCollectTime = twoMonthAgo;
                }
            } else {
                // 避免防止漏票，提前两个小时
                try {
                    Date date = simpleDateFormat.parse(lastCollectTime);
                    Calendar cal = Calendar.getInstance();
                    cal.setTime(date);
                    cal.add(Calendar.HOUR_OF_DAY, -2);
                    date = cal.getTime();
                    //如果date 小于两个月前，则用两个月前，否则用date
                    if(date.compareTo(DateUtils.strToDate(twoMonthAgo, "yyyyMMddHHmmss"))<0){
                        lastCollectTime = twoMonthAgo;
                    }else{
                        lastCollectTime = simpleDateFormat.format(date);
                    }
                } catch (ParseException e) {
                    log.debug("业务异常：{}",e);
                }
            }
        } catch (ParseException e) {
            log.info("处理异常:{}",e);
        }

        return lastCollectTime;
    }

    public static void main(String[] args) {
        System.out.println(getBeginTimeGj("20240317000000", null));
        System.out.println(getBeginTimeGj("20230317000000", null));
        System.out.println(getBeginTimeGj("20230317000000", new Date()));
        System.out.println(getBeginTimeGj("20240317000000", new Date()));
    }

    /**
     * 获取结束时间
     *
     * @return
     */
    public static String getEndTime() {
        Calendar c2 = new GregorianCalendar();
        c2.set(Calendar.HOUR_OF_DAY, 23);
        c2.set(Calendar.MINUTE, 59);
        c2.set(Calendar.SECOND, 59);
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
        return simpleDateFormat.format(c2.getTime());
    }
    /**
     * 加密方法
     */
    public static String makeAppSec(String data, String dataExchangeId, String interfaceCode, String aceId, String aceKey) {
        String srcStr =
                "POST/rest/invoice/dii?authorize={\"appSecId\":\"" + aceId + "\"}&globalInfo={\"appId\":\"" + CoreConstants.appId
                        + "\",\"version\":\"" + CoreConstants.version + "\",\"interfaceCode\":\"" + interfaceCode + "\",\"enterpriseCode\":\""
                        + CoreConstants.enterpriseCode + "\",\"dataExchangeId\":\"" + dataExchangeId + "\"}&" + "data=" + data + "";
        log.info("待加密的请求：" + srcStr);
        SecretKeySpec keySpec = null;
        keySpec = new SecretKeySpec(aceKey.getBytes(StandardCharsets.UTF_8), "HmacSHA1");
        Mac mac = null;
        try {
            mac = Mac.getInstance("HmacSHA1");
        } catch (NoSuchAlgorithmException e) {
           log.info("业务处理异常：{}", e);
        }
        try {
            mac.init(keySpec);
        } catch (InvalidKeyException e) {
           log.info("业务处理异常：{}", e);
        }
        byte[] singBytes = new byte[0];
        singBytes = mac.doFinal(srcStr.getBytes(StandardCharsets.UTF_8));
        String appSec = Base64.encode(singBytes);
        log.info("interfaceCode接口生成的加密串=appSec--");
        return appSec;
    }
}