package com.oguerreiro.resilient.config;

import java.util.ArrayList;
import java.util.List;

import org.springframework.boot.ApplicationRunner;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.type.filter.AnnotationTypeFilter;

import com.oguerreiro.resilient.repository.security.SecurityResourceRepository;
import com.oguerreiro.resilient.security.custom.ResilientSecurityResourceConfig;
import com.oguerreiro.resilient.security.resillient.SecurityResource;

@Configuration
public class SecurityResourcesConfiguration {
  @Bean
  ApplicationRunner runner(SecurityResourceRepository securityResourceRepository) {
    return args -> {
      List<Class<?>> result = this.findAnnotatedClasses("com.oguerreiro.resilient");

      result.forEach(c -> {
        String code = c.getName();
        String name = c.getSimpleName();
        ResilientSecurityResourceConfig annotation = c.getAnnotation(ResilientSecurityResourceConfig.class);

        if (!annotation.code().equals(ResilientSecurityResourceConfig.DEFAULT_CODE)) {
          code = annotation.code();
        }

        if (securityResourceRepository.findByCode(code).isEmpty()) {
          //Insert new value
          SecurityResource newSecurityResource = new SecurityResource().type(annotation.type()).code(code).name(
              name).defaultCreatePermission(annotation.defaultCreatePermission()).defaultReadPermission(
                  annotation.defaultReadPermission()).defaultUpdatePermission(
                      annotation.defaultUpdatePermission()).defaultDeletePermission(
                          annotation.defaultDeletePermission());
          securityResourceRepository.save(newSecurityResource);
        }
      });
    };
  }

  public List<Class<?>> findAnnotatedClasses(String basePackage) {
    List<Class<?>> classes = new ArrayList<>();

    // Create a scanner and add a filter for the annotation
    var scanner = new ClassPathScanningCandidateComponentProvider(false);
    scanner.addIncludeFilter(new AnnotationTypeFilter(ResilientSecurityResourceConfig.class));

    for (var beanDef : scanner.findCandidateComponents(basePackage)) {
      try {
        Class<?> clazz = Class.forName(beanDef.getBeanClassName());
        classes.add(clazz);
      } catch (ClassNotFoundException e) {
        throw new RuntimeException("Class not found: " + beanDef.getBeanClassName(), e);
      }
    }

    return classes;
  }
}
