package com.kamco.cd.kamcoback.menu.service;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.kamco.cd.kamcoback.common.enums.RoleType;
import com.kamco.cd.kamcoback.common.utils.UserUtil;
import com.kamco.cd.kamcoback.menu.dto.MenuDto;
import com.kamco.cd.kamcoback.postgres.core.MenuCoreService;
import java.util.ArrayList;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

@Service
@RequiredArgsConstructor
public class MenuService {

  private final MenuCoreService menuCoreService;
  private final StringRedisTemplate redisTemplate;
  private final ObjectMapper objectMapper;
  private final UserUtil userUtil;

  @Cacheable(value = "menuFindAll")
  public List<MenuDto.Basic> getFindAll() {
    return menuCoreService.getFindAll();
  }

  /**
   * 권한별 메뉴 목록 redis 등록
   *
   * @return
   */
  public void getFindByRoleRedis() {

    for (RoleType role : RoleType.values()) {
      List<MenuDto.Basic> menus = menuCoreService.getFindByRole(role.name());

      try {
        String key = "menu:role:" + role.name();
        String value = objectMapper.writeValueAsString(menus);
        redisTemplate.opsForValue().set(key, value);
      } catch (JsonProcessingException e) {
        throw new RuntimeException(e);
      }
    }

    List<MenuDto.MenuWithRolesDto> menusWithRoles = menuCoreService.getMenuWithRoles();

    try {
      String key = "auth:api:role";
      String value = objectMapper.writeValueAsString(menusWithRoles);
      redisTemplate.opsForValue().set(key, value);
    } catch (JsonProcessingException e) {
      throw new RuntimeException(e);
    }
  }

  /**
   * 권한별 메뉴 목록 조회
   *
   * @param role
   * @return
   */
  public List<MenuDto.Basic> getFindByRole(String role) {
    String key = "menu:role:" + role;
    String json = redisTemplate.opsForValue().get(key);
    if (json == null) {
      return new ArrayList<>();
    }

    JavaType type =
        objectMapper.getTypeFactory().constructCollectionType(List.class, MenuDto.Basic.class);

    List<MenuDto.Basic> cached;

    try {
      cached = objectMapper.readValue(json, type);
    } catch (JsonProcessingException e) {
      throw new RuntimeException(e);
    }
    return cached;
  }
}
