package tv.pluto.utils;

import com.google.gson.annotations.SerializedName;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Random;
import java.util.Set;
import tv.pluto.grpc.genres.Genre;
import tv.pluto.grpc.genres.Genres;
import tv.pluto.ip.dal.genre.Genres.GetGenreSubGenreMapResponse;

public class GenreUtils {
  public List<Genre> toGenreSubGenreMap(GetGenreSubGenreMapResponse response) {
    List<Genre> result = new ArrayList<>();

    response
        .getGenreSubGenresList()
        .forEach(
            genre -> {
              result.add(new Genre(genre.getGenre(), genre.getSubGenresList()));
            });

    return result;
  }

  @SuppressWarnings({"unchecked"})
  public List<Genre> toSubGenreMap(Genres obj)
      throws InvocationTargetException, IllegalAccessException {
    List<Genre> result = new ArrayList<>();

    Field[] allFields = Genres.class.getDeclaredFields();
    Method[] allMethods = Genres.class.getDeclaredMethods();
    for (Field field : allFields) {
      SerializedName serializedName = field.getAnnotation(SerializedName.class);

      String genreName = serializedName.value();
      Method getter =
          Arrays.stream(allMethods)
              .filter(
                  method ->
                      method.getName().startsWith("get")
                          && method.getName().toLowerCase().endsWith(field.getName().toLowerCase()))
              .findFirst()
              .orElseThrow(() -> new RuntimeException("Getter not found"));

      List<String> subGenres = (List<String>) getter.invoke(obj);

      result.add(new Genre(genreName, subGenres));
    }

    return result;
  }

  public List<String> getGenresFromAnnotations() {
    List<String> result = new ArrayList<>();

    Field[] allFields = Genres.class.getDeclaredFields();
    for (Field field : allFields) {
      SerializedName serializedName = field.getAnnotation(SerializedName.class);

      if (serializedName != null) {
        result.add(serializedName.value());
      }
    }

    return result;
  }

  @SuppressWarnings({"unchecked"})
  public List<String> getSubGenresByAnnotation(String categoryName, Genres obj)
      throws InvocationTargetException, IllegalAccessException {
    Field[] allFields = Genres.class.getDeclaredFields();
    Method[] allMethods = Genres.class.getDeclaredMethods();

    Field field =
        Arrays.stream(allFields)
            .filter(fld -> fld.getAnnotation(SerializedName.class).value().equals(categoryName))
            .findFirst()
            .orElseThrow(() -> new RuntimeException("Field not found"));

    Method getter =
        Arrays.stream(allMethods)
            .filter(
                method ->
                    method.getName().startsWith("get")
                        && method.getName().toLowerCase().endsWith(field.getName().toLowerCase()))
            .findFirst()
            .orElseThrow(() -> new RuntimeException("Getter not found"));

    return (List<String>) getter.invoke(obj);
  }

  public <T> T getRandomItem(List<T> list) {
    return list.get(new Random().nextInt(list.size()));
  }

  public static final Set<String> deletedGenresSet =
      Set.of(
          "Classics",
          "Dance",
          "Gay & Lesbian",
          "Independent",
          "Musicals",
          "Other",
          "Private Channel",
          "Documentaries",
          "Faith and Spirituality",
          "News and Information",
          "Thrillers");
}
