package org.xyzh.common.redis.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.RedisCallback;
import java.util.*;
import java.util.concurrent.TimeUnit;
import org.springframework.stereotype.Component;

/**
 * @description    RedisService.java Redis工具服务类，封装常用Redis操作
 * @filename    RedisService.java
 * @author    yslg
 * @copyright xyzh
 * @since 2025-09-07
 */
@SuppressWarnings(value = { "unchecked", "rawtypes" })
@Component
public class RedisService {
    
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    /**
     * @description    设置key-value
     * @param key String 键
     * @param value Object 值
     * @author yslg
     * @since 2025-09-07
     */
    public void set(String key, Object value) {
        redisTemplate.opsForValue().set(key, value);
    }

    /**
     * @description    设置key-value并指定过期时间
     * @param key String 键
     * @param value Object 值
     * @param timeout long 过期时间
     * @param unit TimeUnit 时间单位
     * @author yslg
     * @since 2025-09-07
     */
    public void set(String key, Object value, long timeout, TimeUnit unit) {
        redisTemplate.opsForValue().set(key, value, timeout, unit);
    }

    /**
     * @description    获取key对应的value
     * @param key String 键
     * @return Object 值
     * @author yslg
     * @since 2025-09-07
     */
    public Object get(String key) {
        return redisTemplate.opsForValue().get(key);
    }

    /**
     * @description    删除key
     * @param key String 键
     * @author yslg
     * @since 2025-09-07
     */
    public void delete(String key) {
        redisTemplate.delete(key);
    }

    /**
     * @description    批量删除key
     * @param keys Collection<String> 键集合
     * @author yslg
     * @since 2025-09-07
     */
    public void delete(Collection<String> keys) {
        redisTemplate.delete(keys);
    }

    /**
     * @description    判断key是否存在
     * @param key String 键
     * @return boolean 是否存在
     * @author yslg
     * @since 2025-09-07
     */
    public boolean hasKey(String key) {
        return redisTemplate.hasKey(key);
    }

    /**
     * @description    设置key过期时间（秒）
     * @param key String 键
     * @param timeout long 过期秒数
     * @author yslg
     * @since 2025-09-07
     */
    public void setExpire(String key, long timeout) {
        redisTemplate.expire(key, timeout, TimeUnit.SECONDS);
    }

    /**
     * @description    设置key过期时间（自定义单位）
     * @param key String 键
     * @param timeout long 过期时间
     * @param unit TimeUnit 时间单位
     * @author yslg
     * @since 2025-09-07
     */
    public void setExpire(String key, long timeout, TimeUnit unit) {
        redisTemplate.expire(key, timeout, unit);
    }

    /**
     * @description    获取key剩余过期时间（秒）
     * @param key String 键
     * @return long 剩余秒数
     * @author yslg
     * @since 2025-09-07
     */
    public long getExpire(String key) {
        return redisTemplate.getExpire(key, TimeUnit.SECONDS);
    }

    /**
     * @description    原子递增
     * @param key String 键
     * @param delta long 增量
     * @return long 递增后值
     * @author yslg
     * @since 2025-09-07
     */
    public long incr(String key, long delta) {
        Long result = redisTemplate.opsForValue().increment(key, delta);
        return result != null ? result : 0L;
    }

    /**
     * @description    原子递减
     * @param key String 键
     * @param delta long 减量
     * @return long 递减后值
     * @author yslg
     * @since 2025-09-07
     */
    public long decr(String key, long delta) {
        Long result = redisTemplate.opsForValue().increment(key, -delta);
        return result != null ? result : 0L;
    }

    /**
     * @description    Hash操作-put
     * @param key String 键
     * @param hashKey String 哈希键
     * @param value Object 值
     * @author yslg
     * @since 2025-09-07
     */
    public void hSet(String key, String hashKey, Object value) {
        redisTemplate.opsForHash().put(key, hashKey, value);
    }

    /**
     * @description    Hash操作-get
     * @param key String 键
     * @param hashKey String 哈希键
     * @return Object 值
     * @author yslg
     * @since 2025-09-07
     */
    public Object hGet(String key, String hashKey) {
        return redisTemplate.opsForHash().get(key, hashKey);
    }

    /**
     * @description    Hash操作-获取所有
     * @param key String 键
     * @return Map<Object, Object> 哈希所有键值对
     * @author yslg
     * @since 2025-09-07
     */
    public Map<Object, Object> hGetAll(String key) {
        return redisTemplate.opsForHash().entries(key);
    }

    /**
     * @description    Hash操作-删除
     * @param key String 键
     * @param hashKeys String[] 哈希键数组
     * @author yslg
     * @since 2025-09-07
     */
    public void hDelete(String key, String... hashKeys) {
        redisTemplate.opsForHash().delete(key, (Object[]) hashKeys);
    }

    /**
     * @description    List操作-左入队
     * @param key String 键
     * @param value Object 值
     * @author yslg
     * @since 2025-09-07
     */
    public void lPush(String key, Object value) {
        redisTemplate.opsForList().leftPush(key, value);
    }

    /**
     * @description    List操作-右入队
     * @param key String 键
     * @param value Object 值
     * @author yslg
     * @since 2025-09-07
     */
    public void rPush(String key, Object value) {
        redisTemplate.opsForList().rightPush(key, value);
    }

    /**
     * @description    List操作-左出队
     * @param key String 键
     * @return Object 出队值
     * @author yslg
     * @since 2025-09-07
     */
    public Object lPop(String key) {
        return redisTemplate.opsForList().leftPop(key);
    }

    /**
     * @description    List操作-右出队
     * @param key String 键
     * @return Object 出队值
     * @author yslg
     * @since 2025-09-07
     */
    public Object rPop(String key) {
        return redisTemplate.opsForList().rightPop(key);
    }

    /**
     * @description    List操作-获取区间元素
     * @param key String 键
     * @param start long 起始索引
     * @param end long 结束索引
     * @return List<Object> 元素列表
     * @author yslg
     * @since 2025-09-07
     */
    public List<Object> lRange(String key, long start, long end) {
        return redisTemplate.opsForList().range(key, start, end);
    }

    /**
     * @description    Set操作-添加元素
     * @param key String 键
     * @param values Object[] 元素数组
     * @author yslg
     * @since 2025-09-07
     */
    public void sAdd(String key, Object... values) {
        redisTemplate.opsForSet().add(key, values);
    }

    /**
     * @description    Set操作-移除元素
     * @param key String 键
     * @param values Object[] 元素数组
     * @author yslg
     * @since 2025-09-07
     */
    public void sRemove(String key, Object... values) {
        redisTemplate.opsForSet().remove(key, values);
    }

    /**
     * @description    Set操作-获取所有元素
     * @param key String 键
     * @return Set<Object> 元素集合
     * @author yslg
     * @since 2025-09-07
     */
    public Set<Object> sMembers(String key) {
        return redisTemplate.opsForSet().members(key);
    }

    /**
     * @description    ZSet操作-添加元素
     * @param key String 键
     * @param value Object 元素
     * @param score double 分数
     * @author yslg
     * @since 2025-09-07
     */
    public void zAdd(String key, Object value, double score) {
        redisTemplate.opsForZSet().add(key, value, score);
    }

    /**
     * @description    ZSet操作-移除元素
     * @param key String 键
     * @param values Object[] 元素数组
     * @author yslg
     * @since 2025-09-07
     */
    public void zRemove(String key, Object... values) {
        redisTemplate.opsForZSet().remove(key, values);
    }

    /**
     * @description    ZSet操作-按分数区间获取元素
     * @param key String 键
     * @param min double 最小分数
     * @param max double 最大分数
     * @return Set<Object> 元素集合
     * @author yslg
     * @since 2025-09-07
     */
    public Set<Object> zRangeByScore(String key, double min, double max) {
        return redisTemplate.opsForZSet().rangeByScore(key, min, max);
    }

    /**
     * @description    ZSet操作-获取全部元素
     * @param key String 键
     * @param start long 起始索引
     * @param end long 结束索引
     * @return Set<Object> 元素集合
     * @author yslg
     * @since 2025-09-07
     */
    public Set<Object> zRange(String key, long start, long end) {
        return redisTemplate.opsForZSet().range(key, start, end);
    }

    /**
     * @description    发布消息（Pub/Sub）
     * @param channel String 通道
     * @param message Object 消息内容
     * @author yslg
     * @since 2025-09-07
     */
    public void publish(String channel, Object message) {
        redisTemplate.convertAndSend(channel, message);
    }

    /**
     * @description    执行Redis原生命令
     * @param action RedisCallback<?> 回调命令
     * @return Object 执行结果
     * @author yslg
     * @since 2025-09-07
     */
    public Object execute(RedisCallback<?> action) {
        return redisTemplate.execute(action);
    }

    /**
     * @description    获取所有key（慎用）
     * @param pattern String 匹配模式
     * @return Set<String> key集合
     * @author yslg
     * @since 2025-09-07
     */
    public Set<String> keys(String pattern) {
        Set<String> keys = redisTemplate.keys(pattern);
        Set<String> stringKeys = new HashSet<>();
        if (keys != null) {
            for (String key : keys) {
                stringKeys.add(key);
            }
        }
        return stringKeys;
    }

    /**
     * @description    清空当前数据库（慎用）
     * @author yslg
     * @since 2025-09-07
     */
    public void flushDb() {
        redisTemplate.execute((RedisCallback<Void>) connection -> { connection.flushDb(); return null; });
    }

}
