package com.arms.api.util.redisrepo;

import org.springframework.data.redis.core.Cursor;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ScanOptions;
import org.springframework.stereotype.Component;

import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;

@Component
public class RedisHashCommand {

    private final RedisTemplate<String, Object> redisTemplate;

    //Todo : 기존에 존재하는 코드인것처럼 명을 작성하지말것, 추후에 이것은 개인이 만든것이라는 것을 인지할 수있도록 수정
    public RedisHashCommand(RedisTemplate<String, Object> redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    // ── 조회 ──

    /**
     * Hash의 특정 필드 값을 조회 (HGET)
     */
    public Object get(String key, String field) {
        return redisTemplate.opsForHash().get(key, field);
    }

    /**
     * Hash의 여러 필드 값을 한번에 조회 (HMGET)
     */
    public List<Object> getMulti(String key, Collection<Object> fields) {
        return redisTemplate.opsForHash().multiGet(key, fields);
    }

    /**
     * Hash의 모든 필드와 값을 조회 (HGETALL)
     */
    public Map<Object, Object> getAll(String key) {
        return redisTemplate.opsForHash().entries(key);
    }

    /**
     * Hash의 모든 필드(key) 목록을 조회 (HKEYS)
     */
    public Set<Object> keys(String key) {
        return redisTemplate.opsForHash().keys(key);
    }

    /**
     * Hash의 모든 값(value) 목록을 조회 (HVALS)
     */
    public List<Object> values(String key) {
        return redisTemplate.opsForHash().values(key);
    }

    /**
     * Hash의 필드 개수를 조회 (HLEN)
     */
    public Long size(String key) {
        return redisTemplate.opsForHash().size(key);
    }

    /**
     * Hash에 특정 필드가 존재하는지 확인 (HEXISTS)
     */
    public Boolean hasKey(String key, String field) {
        return redisTemplate.opsForHash().hasKey(key, field);
    }

    // ── 저장 ──

    /**
     * Hash에 필드와 값을 저장 (HSET)
     */
    public void set(String key, String field, Object value) {
        redisTemplate.opsForHash().put(key, field, value);
    }

    /**
     * Hash에 여러 필드와 값을 한번에 저장 (HMSET)
     */
    public void setAll(String key, Map<String, ?> entries) {
        redisTemplate.opsForHash().putAll(key, entries);
    }

    /**
     * Hash에 필드가 없을 때만 저장 (HSETNX)
     */
    public Boolean setIfAbsent(String key, String field, Object value) {
        return redisTemplate.opsForHash().putIfAbsent(key, field, value);
    }

    // ── 삭제 ──

    /**
     * Hash의 특정 필드를 삭제 (HDEL)
     */
    public Long delete(String key, String... fields) {
        return redisTemplate.opsForHash().delete(key, (Object[]) fields);
    }

    // ── 증감 ──

    /**
     * Hash 필드의 값을 정수만큼 증가 (HINCRBY)
     */
    public Long increment(String key, String field, long delta) {
        return redisTemplate.opsForHash().increment(key, field, delta);
    }

    /**
     * Hash 필드의 값을 실수만큼 증가 (HINCRBYFLOAT)
     */
    public Double incrementFloat(String key, String field, double delta) {
        return redisTemplate.opsForHash().increment(key, field, delta);
    }

    // ── 스캔 ──

    /**
     * Hash 필드를 패턴으로 스캔 (HSCAN)
     */
    public Cursor<Map.Entry<Object, Object>> scan(String key, ScanOptions options) {
        return redisTemplate.opsForHash().scan(key, options);
    }

}
