package com.m2pool.common.security.service;

import com.m2pool.common.core.constant.CacheConstants;
import com.m2pool.common.core.constant.OpenApiKeyConstants;
import com.m2pool.common.core.utils.OpenApiJwtUtils;
import com.m2pool.common.core.utils.ServletUtils;
import com.m2pool.common.core.utils.StringUtils;
import com.m2pool.common.core.utils.ip.IpUtils;
import com.m2pool.common.redis.service.RedisService;
import com.m2pool.common.security.utils.OpenApiUtils;
import com.m2pool.system.api.model.OpenApiKeyInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @Description open api key 验证处理
 * @Date 2024/6/13 21:06
 * @Author dy
 */
@Component
public class OpenApiService {

    @Autowired
    private RedisService redisService;

    /** 秒 */
    protected static final long MILLIS_SECOND = 1000;

    /** 分 */
    protected static final long MILLIS_MINUTE = 60 * MILLIS_SECOND;

    /** 过期时间/缓存有效期 设置为1年*/
    private final static long expireTime = CacheConstants.EXPIRATION * 2;

    /** 权限缓存前缀 */
    private final static String ACCESS_API_KEY = CacheConstants.OPEN_API_KEY;

    /** 缓存刷新时间 */
    private final static Long MILLIS_MINUTE_TEN = CacheConstants.REFRESH_TIME * MILLIS_MINUTE;

    /**
     * 创建令牌
     */
    public Map<String, Object> createApiKey(OpenApiKeyInfo openApiKey)
    {
        String apiKey = openApiKey.getKey();
        System.out.println("生成的apiKey:"+apiKey);
        String user = openApiKey.getUser();
        String apiIp = openApiKey.getApiIp();
        openApiKey.setKey(apiKey);
        openApiKey.setUser(user);
        if (StringUtils.isNotBlank(apiIp)){
            openApiKey.setApiIp(apiIp);
        }else {
            openApiKey.setApiIp(IpUtils.getIpAddr(ServletUtils.getRequest()));
        }

        refreshApiKey(openApiKey);

        // Jwt存储信息
        Map<String, Object> claimsMap = new HashMap<String, Object>();
        claimsMap.put(OpenApiKeyConstants.API_KEY, apiKey);
        claimsMap.put(OpenApiKeyConstants.API_USER, user);
        claimsMap.put(OpenApiKeyConstants.API_IP, openApiKey.getApiIp());

        // 接口返回信息
        Map<String, Object> rspMap = new HashMap<String, Object>();
        rspMap.put("api_key", OpenApiJwtUtils.createApiKey(claimsMap));
        rspMap.put("uuid生成的api_key", apiKey);
        rspMap.put("expires_in", expireTime);
        rspMap.put("user", user);
        return rspMap;
    }

    /**
     * 获取apiKey信息
     *
     * @return apiKey信息
     */
    public OpenApiKeyInfo getOpenApiKeyInfo()
    {
        return getOpenApiKeyInfo(ServletUtils.getRequest());
    }

    /**
     * 获取apiKey信息
     *
     * @return apiKey信息
     */
    public OpenApiKeyInfo getOpenApiKeyInfo(HttpServletRequest request)
    {
        // 获取请求携带的令牌
        String apiKey = OpenApiUtils.getApiKey(request);
        return getOpenApiKeyInfo(apiKey);
    }

    /**
     * 获取用户身份信息
     *
     * @return 用户信息
     */
    public OpenApiKeyInfo getOpenApiKeyInfo(String apiKey)
    {
        OpenApiKeyInfo openApiKey = null;
        try
        {
            if (StringUtils.isNotEmpty(apiKey))
            {
                String key = OpenApiJwtUtils.getApiKey(apiKey);
                openApiKey = redisService.getCacheObject(getAPIRedisKey(key));
                return openApiKey;
            }
        }
        catch (Exception e)
        {
            System.out.println("oapiService.getOpenApiKeyInfo 异常");
            e.printStackTrace();
        }
        return openApiKey;
    }

    /**
     * 设置用户api_key信息
     */
    public void setOpenApiKeyInfo(OpenApiKeyInfo openApiKey)
    {
        if (StringUtils.isNotNull(openApiKey) && StringUtils.isNotEmpty(openApiKey.getKey()))
        {
            refreshApiKey(openApiKey);
        }
    }

    /**
     * 删除api_key缓存信息
     */
    public void delOpenApiKey(String apiKey)
    {
        if (StringUtils.isNotEmpty(apiKey))
        {
            String key = OpenApiJwtUtils.getApiKey(apiKey);
            //System.out.println("用户登出，从redis删除key："+api_key:...);
            redisService.deleteObject(getAPIRedisKey(key));
        }
    }

    /**
     * 验证令牌有效期，相差不足120分钟，自动刷新缓存
     *
     * @param openApiKey
     */
    public void verifyApiKey(OpenApiKeyInfo openApiKey)
    {
        long expireTime = openApiKey.getExpireTime();
        long currentTime = System.currentTimeMillis();
        //可以考虑直接刷新缓存 而不是小于才刷新缓存
        if (expireTime - currentTime <= MILLIS_MINUTE_TEN)
        {
            refreshApiKey(openApiKey);
        }
    }

    /**
     * 刷新api-key有效期
     *
     * @param openApiKey api-key请求信息
     */
    public void refreshApiKey(OpenApiKeyInfo openApiKey)
    {
        openApiKey.setLoginTime(System.currentTimeMillis());
        openApiKey.setExpireTime(openApiKey.getLoginTime() + expireTime * MILLIS_MINUTE);
        // 根据uuid将api-key缓存
        String apiKey = getAPIRedisKey(openApiKey.getKey());
        redisService.setCacheObject(apiKey, openApiKey, expireTime, TimeUnit.MINUTES);
    }

    private String getAPIRedisKey(String token)
    {
        return ACCESS_API_KEY + token;
    }

}
