package com.skr.mdm.config;

import com.skr.mdm.authentication.user.UserAuthenticationEntryPoint;
import com.skr.mdm.authentication.user.UserAuthenticationFailureHandler;
import com.skr.mdm.authentication.user.UserAuthenticationSuccessHandler;
import com.skr.mdm.authentication.user.UserLogoutSuccessHandler;
import com.skr.mdm.authentication.user.imei.ImeiAuthenticationFilter;
import com.skr.mdm.authentication.user.imei.ImeiAuthenticationProvider;
import com.skr.mdm.authentication.user.imei.ImeiUserDetailsServiceImpl;
import com.skr.mdm.authentication.user.oaid.OaidAuthenticationFilter;
import com.skr.mdm.authentication.user.oaid.OaidAuthenticationProvider;
import com.skr.mdm.authentication.user.oaid.OaidUserDetailsServiceImpl;
import com.skr.mdm.authentication.user.qr.UsernameAuthenticationFilter;
import com.skr.mdm.authentication.user.qr.UsernameAuthenticationProvider;
import com.skr.mdm.authentication.user.qr.UsernameDetailsServiceImpl;
import com.skr.mdm.authentication.user.sms.SmsAuthenticationFilter;
import com.skr.mdm.authentication.user.sms.SmsAuthenticationProvider;
import com.skr.mdm.authentication.user.sms.SmsDetailsServiceImpl;
import com.skr.mdm.authentication.user.uuid.UuidAuthenticationFilter;
import com.skr.mdm.authentication.user.uuid.UuidAuthenticationProvider;
import com.skr.mdm.authentication.user.uuid.UuidUserDetailsServiceImpl;
import com.skr.mdm.dao.AuCompanyDao;
import com.skr.mdm.dao.DeviceEquipmentDao;
import com.skr.mdm.filter.UserPreventReplayFilter;
import com.skr.mdm.filter.UserTokenFilter;
import com.skr.mdm.rabbitmq.RabbitMQProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
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.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

/**
 * @author nfq
 * @date 2020/7/15 12:11
 */
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Value("${mdm.encrypt}")
    private String mdmEncrypt;

    @Autowired
    private UserAuthenticationSuccessHandler userAuthenticationSuccessHandler;
    @Autowired
    private UserAuthenticationFailureHandler userAuthenticationFailureHandler;
    @Autowired
    private ImeiUserDetailsServiceImpl imeiUserDetailsService;
    @Autowired
    private UsernameDetailsServiceImpl usernameDetailsService;
    @Autowired
    private UserAuthenticationEntryPoint userAuthenticationEntryPoint;
    @Autowired
    private UserTokenFilter userTokenFilter;
    @Autowired
    private UserLogoutSuccessHandler userLogoutSuccessHandler;
    @Autowired
    private DeviceEquipmentDao equipmentDao;
    @Autowired
    private AuCompanyDao companyDao;
    @Autowired
    private RabbitMQProvider rabbitMQProvider;
    @Autowired
    private OaidUserDetailsServiceImpl oaidUserDetailsService;
    @Autowired
    private UuidUserDetailsServiceImpl uuidUserDetailsService;
    @Autowired
    private SmsDetailsServiceImpl smsDetailsService;
    @Autowired
    private UserPreventReplayFilter userPreventReplayFilter;

    @Override
    public void configure(WebSecurity web) throws Exception {

    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable();
        http.authorizeRequests()
                .antMatchers("/swagger-ui.html").permitAll()
                .antMatchers("/webjars/**").permitAll()
                .antMatchers("/v2/**").permitAll()
                .antMatchers("/swagger-resources/**").permitAll()
                .antMatchers("/user/refresh/token").permitAll()
                .antMatchers("/**/*.js").permitAll()
                .antMatchers("/lang/*.json").permitAll()
                .antMatchers("/**/*.css").permitAll()
                .antMatchers("/doc.html").permitAll()
                .antMatchers("/druid/**").permitAll()
                .antMatchers("/favicon.ico").permitAll()
                .antMatchers("/**/*.jpg").permitAll()
                .antMatchers("/**/*.png").permitAll()
                .antMatchers("/**/*.apk").permitAll()
                .antMatchers("/mdm/actuator/**").permitAll()
                .anyRequest()
                .authenticated()
                .and()
                .formLogin()
                .successHandler(userAuthenticationSuccessHandler)
                .failureHandler(userAuthenticationFailureHandler)
                .and()
                .exceptionHandling()
                .authenticationEntryPoint(userAuthenticationEntryPoint)
                .and()
                .logout()
                .logoutSuccessHandler(userLogoutSuccessHandler);

        http.addFilterAfter(imeiAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
        http.addFilterAfter(oaidAuthenticationFilter(), ImeiAuthenticationFilter.class);
        http.addFilterAfter(uuidAuthenticationFilter(), OaidAuthenticationFilter.class);
        http.addFilterAfter(usernameAuthenticationFilter(), UuidAuthenticationFilter.class);
        http.addFilterAfter(smsAuthenticationFilter(), UsernameAuthenticationFilter.class);
        http.addFilterBefore(userTokenFilter, ImeiAuthenticationFilter.class);
        http.addFilterBefore(userPreventReplayFilter, UserTokenFilter.class);
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.authenticationProvider(imeiAuthenticationProvider()).authenticationProvider(usernameAuthenticationProvider())
                .authenticationProvider(oaidAuthenticationProvider()).authenticationProvider(uuidAuthenticationProvider())
                .authenticationProvider(smsAuthenticationProvider());
    }

    @Override
    @Bean
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    /**
     * imei登录
     * @return
     * @throws Exception
     */
    @Bean
    public ImeiAuthenticationFilter imeiAuthenticationFilter() throws Exception {
        ImeiAuthenticationFilter imeiAuthenticationFilter = new ImeiAuthenticationFilter();
        imeiAuthenticationFilter.setMdmEncrypt(mdmEncrypt);
        imeiAuthenticationFilter.setAuthenticationManager(authenticationManagerBean());
        imeiAuthenticationFilter.setAuthenticationSuccessHandler(userAuthenticationSuccessHandler);
        imeiAuthenticationFilter.setAuthenticationFailureHandler(userAuthenticationFailureHandler);
        return imeiAuthenticationFilter;
    }

    @Bean
    public ImeiAuthenticationProvider imeiAuthenticationProvider() {
        ImeiAuthenticationProvider imeiAuthenticationProvider = new ImeiAuthenticationProvider();
        imeiAuthenticationProvider.setUserDetailsService(imeiUserDetailsService);
        return imeiAuthenticationProvider;
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    /**
     * 用户密码注册并登录
     * @return
     * @throws Exception
     */
    @Bean
    public UsernameAuthenticationFilter usernameAuthenticationFilter() throws Exception {
        UsernameAuthenticationFilter usernameAuthenticationFilter = new UsernameAuthenticationFilter();
        usernameAuthenticationFilter.setMdmEncrypt(mdmEncrypt);
        usernameAuthenticationFilter.setAuthenticationManager(authenticationManagerBean());
        usernameAuthenticationFilter.setAuthenticationSuccessHandler(userAuthenticationSuccessHandler);
        usernameAuthenticationFilter.setAuthenticationFailureHandler(userAuthenticationFailureHandler);
        return usernameAuthenticationFilter;
    }

    @Bean
    public UsernameAuthenticationProvider usernameAuthenticationProvider() {
        UsernameAuthenticationProvider usernameAuthenticationProvider = new UsernameAuthenticationProvider();
        usernameAuthenticationProvider.setUserDetailsService(usernameDetailsService);
        usernameAuthenticationProvider.setPasswordEncoder(passwordEncoder());
        usernameAuthenticationProvider.setEquipmentDao(equipmentDao);
        usernameAuthenticationProvider.setCompanyDao(companyDao);
        usernameAuthenticationProvider.setRabbitMQProvider(rabbitMQProvider);
        return usernameAuthenticationProvider;
    }

    /**
     * oaid登录
     * @return
     * @throws Exception
     */
    @Bean
    public OaidAuthenticationFilter oaidAuthenticationFilter() throws Exception {
        OaidAuthenticationFilter oaidAuthenticationFilter = new OaidAuthenticationFilter();
        oaidAuthenticationFilter.setMdmEncrypt(mdmEncrypt);
        oaidAuthenticationFilter.setAuthenticationManager(authenticationManagerBean());
        oaidAuthenticationFilter.setAuthenticationSuccessHandler(userAuthenticationSuccessHandler);
        oaidAuthenticationFilter.setAuthenticationFailureHandler(userAuthenticationFailureHandler);
        return oaidAuthenticationFilter;
    }

    @Bean
    public OaidAuthenticationProvider oaidAuthenticationProvider() {
        OaidAuthenticationProvider oaidAuthenticationProvider = new OaidAuthenticationProvider();
        oaidAuthenticationProvider.setUserDetailsService(oaidUserDetailsService);
        return oaidAuthenticationProvider;
    }

    /**
     * uuid登录
     * @return
     * @throws Exception
     */
    @Bean
    public UuidAuthenticationFilter uuidAuthenticationFilter() throws Exception {
        UuidAuthenticationFilter uuidAuthenticationFilter = new UuidAuthenticationFilter();
        uuidAuthenticationFilter.setMdmEncrypt(mdmEncrypt);
        uuidAuthenticationFilter.setAuthenticationManager(authenticationManagerBean());
        uuidAuthenticationFilter.setAuthenticationSuccessHandler(userAuthenticationSuccessHandler);
        uuidAuthenticationFilter.setAuthenticationFailureHandler(userAuthenticationFailureHandler);
        return uuidAuthenticationFilter;
    }

    @Bean
    public UuidAuthenticationProvider uuidAuthenticationProvider() {
        UuidAuthenticationProvider uuidAuthenticationProvider = new UuidAuthenticationProvider();
        uuidAuthenticationProvider.setUserDetailsService(uuidUserDetailsService);
        return uuidAuthenticationProvider;
    }
    /**
     * 短信登录-注册
     * @return
     * @throws Exception
     */
    @Bean
    public SmsAuthenticationFilter smsAuthenticationFilter() throws Exception {
        SmsAuthenticationFilter smsAuthenticationFilter = new SmsAuthenticationFilter();
        smsAuthenticationFilter.setMdmEncrypt(mdmEncrypt);
        smsAuthenticationFilter.setAuthenticationManager(authenticationManagerBean());
        smsAuthenticationFilter.setAuthenticationSuccessHandler(userAuthenticationSuccessHandler);
        smsAuthenticationFilter.setAuthenticationFailureHandler(userAuthenticationFailureHandler);
        return smsAuthenticationFilter;
    }

    @Bean
    public SmsAuthenticationProvider smsAuthenticationProvider() {
        SmsAuthenticationProvider smsAuthenticationProvider = new SmsAuthenticationProvider();
        smsAuthenticationProvider.setCompanyDao(companyDao);
        smsAuthenticationProvider.setEquipmentDao(equipmentDao);
        smsAuthenticationProvider.setUserDetailsService(smsDetailsService);
        smsAuthenticationProvider.setRabbitMQProvider(rabbitMQProvider);
        return smsAuthenticationProvider;
    }
}