package br.com.cadmea.spring.config;
import br.com.cadmea.spring.beans.TokenService;
import br.com.cadmea.spring.beans.UserDetailsSrv;
import br.com.cadmea.spring.dao.UserSystemRepository;
import br.com.cadmea.spring.rest.ServicePath;
import br.com.cadmea.spring.security.JWTAuthorizationFilter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletResponse;
@Slf4j
@Configuration
@EnableWebSecurity
//@EnableGlobalMethodSecurity(prePostEnabled = true)
@Import({ UserDetailsSrv.class, TokenService.class })
public class SecurityConfig extends WebSecurityConfigurerAdapter {
  @Value("${spring.profiles.active}")
  private String profile;
  @Value("${cadmea.users.roles:ADMIN}")
  private String ROLES;
  @Autowired
  private UserDetailsSrv userService;
  @Autowired
  private TokenService tokenService;
  @Autowired
  private UserSystemRepository userSystemRepository;
  @PostConstruct
  public void init() {
    log.info(" security config profile:" + this.profile);
  }
  @Bean
  @Override
  public AuthenticationManager authenticationManager() throws Exception {
    return super.authenticationManager();
  }
  /**
   * define what's going to be ingored
   *
   * @param web
   * @throws Exception
   */
  @Override
  public void configure(final WebSecurity web) throws Exception {
    web.ignoring().antMatchers(publicEndPoints());
  }
  /**
   * define the security algorithmo for password
   *
   * @param auth
   * @throws Exception
   */
  @Override
  protected void configure(final AuthenticationManagerBuilder auth)
      throws Exception {
    auth.userDetailsService(this.userService)
        .passwordEncoder(new BCryptPasswordEncoder());
  }
  /**
   * define what's going to be acceptable for security
   *
   * @param http
   * @throws Exception
   */
  @Override
  protected void configure(final HttpSecurity http) throws Exception {
    http.csrf().disable();
    http.sessionManagement()
        .sessionCreationPolicy(SessionCreationPolicy.STATELESS);
    http.authorizeRequests().antMatchers(publicEndPoints()).permitAll();
    http.authorizeRequests().antMatchers(privateEndpoints())
        .hasAnyAuthority(this.ROLES.split(","));
    http.authorizeRequests().anyRequest().authenticated();
    http.addFilterBefore(new JWTAuthorizationFilter(this.tokenService,
        this.userSystemRepository), UsernamePasswordAuthenticationFilter.class);
  }
  /**
   * @return
   */
  private String[] privateEndpoints() {
    return new String[] { ServicePath.PRIVATE_ROOT_PATH + ServicePath.ALL };
  }
  /**
   * @return
   */
  private String[] publicEndPoints() {
    return new String[] { (ServicePath.PUBLIC_ROOT_PATH + ServicePath.ALL),
        ServicePath.LOGIN_PATH, ServicePath.LOGOUT_PATH, "/error/**",
        "/h2-console/**", "/resources/**", "/v2/rest-docs", "/v2/api-docs",
        "/swagger-resources/configuration", "/swagger-resources", "/**.html",
        "/webjars/**", "/login", "/csrf", "/" };
  }
  @Bean
  public AuthenticationEntryPoint unauthorizedEntryPoint() {
    return (request, response, authException) -> response
        .sendError(HttpServletResponse.SC_UNAUTHORIZED,
            "not authorized by cadmea system");
  }
}