package com.tzld.piaoquan.api.service.impl;

import com.tzld.piaoquan.api.dao.mapper.contentplatform.ContentPlatformAccountMapper;
import com.tzld.piaoquan.api.model.po.contentplatform.ContentPlatformAccount;
import com.tzld.piaoquan.api.model.po.contentplatform.ContentPlatformAccountExample;
import com.tzld.piaoquan.api.model.param.AccessTokenParam;
import com.tzld.piaoquan.api.model.vo.AccessTokenVo;
import com.tzld.piaoquan.api.service.GhAccessTokenService;
import com.tzld.piaoquan.growth.common.common.base.CommonResponse;
import com.tzld.piaoquan.growth.common.common.enums.ExceptionCodeEnum;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

@Slf4j
@Service
public class GhAccessTokenServiceImpl implements GhAccessTokenService {

    private static final String ACCESS_TOKEN_LIST = "access_token_list";

    @Autowired
    private RedisTemplate<String, String> stringRedisTemplate;
    @Autowired
    private ContentPlatformAccountMapper contentPlatformAccountMapper;


    @Override
    public CommonResponse<AccessTokenVo> getAccessToken(AccessTokenParam param) throws RuntimeException {
        if (param == null || StringUtils.isEmpty(param.getSecret())) {
            return CommonResponse.create(ExceptionCodeEnum.PARAMS_ERROR, "未找到 secret");
        }
        ContentPlatformAccount account = getAccountBySecret(param.getSecret());
        if (account == null) {
            return CommonResponse.create(ExceptionCodeEnum.PARAMS_ERROR, "secret 不存在");
        }
        AccessTokenVo accessTokenVo = new AccessTokenVo();
        String accessToken = (String) stringRedisTemplate.opsForValue().get(param.getSecret());
        if (StringUtils.isNotEmpty(accessToken)) {
            Long expire = Long.parseLong(String.valueOf(stringRedisTemplate.getExpire(param.getSecret(), TimeUnit.SECONDS)));
            accessTokenVo.setAccessToken(accessToken);
            accessTokenVo.setExpires(expire);
            if (stringRedisTemplate.opsForHash().size(ACCESS_TOKEN_LIST) > 20) {
                Map<Object, Object> entries = stringRedisTemplate.opsForHash().entries(ACCESS_TOKEN_LIST);
                entries.forEach((k, v) -> {
                    long timestamp = Long.parseLong((String) v);
                    if (System.currentTimeMillis() / 1000 > timestamp) {
                        stringRedisTemplate.opsForHash().delete(ACCESS_TOKEN_LIST, k);
                    }
                });
            }
        } else {
            String newAccessToken = UUID.randomUUID().toString().replace("-", "");
            stringRedisTemplate.opsForValue().set(param.getSecret(), newAccessToken, 2L, TimeUnit.HOURS);
            stringRedisTemplate.opsForValue().set(newAccessToken, param.getSecret(), 3L, TimeUnit.HOURS);
            long expire = 7200L;
            String timestamp = String.valueOf(System.currentTimeMillis() / 1000 + expire + 600);
            stringRedisTemplate.opsForHash().put(ACCESS_TOKEN_LIST, newAccessToken, timestamp);
            accessTokenVo.setAccessToken(newAccessToken);
            accessTokenVo.setExpires(expire);
        }
        return CommonResponse.success(accessTokenVo);
    }

    @Override
    public boolean validateAccessToken(String accessToken) {
        Object o = stringRedisTemplate.opsForHash().get(ACCESS_TOKEN_LIST, accessToken);
        if (o == null) {
            return false;
        }
        long timestamp = Long.parseLong((String) o);
        if (System.currentTimeMillis() / 1000 > timestamp) {
            stringRedisTemplate.opsForHash().delete(ACCESS_TOKEN_LIST, accessToken);
            return false;
        }
        return true;
    }

    @Override
    public ContentPlatformAccount getAccountByAccessToken(String accessToken) {
        String secret = stringRedisTemplate.opsForValue().get(accessToken);
        if (StringUtils.isEmpty(secret)) {
            return null;
        }
        return getAccountBySecret(secret);
    }

    @Override
    public ContentPlatformAccount getAccountBySecret(String secret) {
        ContentPlatformAccountExample example = new ContentPlatformAccountExample();
        example.createCriteria().andReplySecretEqualTo(secret);
        List<ContentPlatformAccount> list = contentPlatformAccountMapper.selectByExample(example);
        if (list.isEmpty()) {
            return null;
        }
        return list.get(0);
    }

}
