package com.kamco.cd.training.common.utils.enums;

import com.kamco.cd.training.common.utils.HeaderUtil;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.reflections.Reflections;

public class Enums {

  private static final String BASE_PACKAGE = "com.kamco.cd.training";

  /** 노출 가능한 enum만 모아둔 맵 key: enum simpleName (예: RoleType) value: enum Class */
  private static final Map<String, Class<? extends Enum<?>>> exposedEnumMap = scanExposedEnumMap();

  // code로 enum 찾기
  public static <E extends Enum<E> & EnumType> E fromId(Class<E> enumClass, String id) {
    if (id == null) {
      return null;
    }

    for (E e : enumClass.getEnumConstants()) {
      if (id.equalsIgnoreCase(e.getId())) {
        return e;
      }
    }
    return null;
  }

  // enum -> CodeDto list
  public static List<CodeDto> toList(Class<? extends Enum<?>> enumClass) {
    Object[] enums = enumClass.getEnumConstants();
    boolean english = HeaderUtil.isEnglishRequest();

    return Arrays.stream(enums)
        .map(e -> (EnumType) e)
        .map(e -> new CodeDto(e.getId(), english ? e.getId() : e.getText()))
        .toList();
  }

  /** 특정 타입(enum)만 조회 /codes/{type} -> type = RoleType 같은 값 */
  public static List<CodeDto> getCodes(String type) {
    Class<? extends Enum<?>> enumClass = exposedEnumMap.get(type);
    if (enumClass == null) {
      throw new IllegalArgumentException("지원하지 않는 코드 타입: " + type);
    }
    return toList(enumClass);
  }

  /** 전체 enum 코드 조회 */
  public static Map<String, List<CodeDto>> getAllCodes() {
    Map<String, List<CodeDto>> result = new HashMap<>();
    for (Map.Entry<String, Class<? extends Enum<?>>> e : exposedEnumMap.entrySet()) {
      result.put(e.getKey(), toList(e.getValue()));
    }
    return result;
  }

  /**
   * @CodeExpose + EnumType 인 enum만 스캔해서 Map 구성
   */
  private static Map<String, Class<? extends Enum<?>>> scanExposedEnumMap() {
    Reflections reflections = new Reflections(BASE_PACKAGE);

    Set<Class<?>> types = reflections.getTypesAnnotatedWith(CodeExpose.class);

    Map<String, Class<? extends Enum<?>>> result = new HashMap<>();

    for (Class<?> clazz : types) {
      if (clazz.isEnum() && EnumType.class.isAssignableFrom(clazz)) {
        result.put(clazz.getSimpleName(), (Class<? extends Enum<?>>) clazz);
      }
    }
    return result;
  }
}
