package com.hepl.tunefortwo.config.security;

import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.util.Arrays;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpStatus;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.oauth2.jose.jws.MacAlgorithm;
import org.springframework.security.oauth2.jwt.JwtDecoder;
import org.springframework.security.oauth2.jwt.NimbusJwtDecoder;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.security.web.authentication.HttpStatusEntryPoint;
import org.springframework.security.web.servlet.util.matcher.MvcRequestMatcher;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.servlet.handler.HandlerMappingIntrospector;

import io.jsonwebtoken.io.Decoders;
import io.jsonwebtoken.security.Keys;
import jakarta.servlet.http.HttpServletResponse;

@Configuration
@EnableWebSecurity
@EnableMethodSecurity(prePostEnabled = true, securedEnabled = false, jsr250Enabled = false)
public class SecurityConfig {

	// Use this for asymmetric key

	// @Value("${rsa.public-key}")
	// RSAPublicKey publicKey;

	// @Value("${rsa.private-key}")
	// RSAPrivateKey privateKey;

	private final CustomAuthenticationEntryPoint entryPoint;

	public SecurityConfig(CustomAuthenticationEntryPoint entryPoint) {
		System.out.println("entryPoint = "+entryPoint);
		this.entryPoint = entryPoint;
	}

	@Bean
	CorsConfigurationSource corsConfigurationSource() {
		CorsConfiguration configuration = new CorsConfiguration();
		configuration.setAllowedOrigins(Arrays.asList("*"));
		configuration.setAllowedMethods(Arrays.asList("*"));
		configuration.setAllowedHeaders(Arrays.asList("*"));
		UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
		source.registerCorsConfiguration("/**", configuration);
		return source;
	}

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

	@Bean
	SecurityFilterChain filterChain(HttpSecurity http, HandlerMappingIntrospector introspector) throws Exception {

        MvcRequestMatcher swaggerUIMatcher = new MvcRequestMatcher(introspector, "/ui");
        MvcRequestMatcher swaggerUIDefaultMatcher = new MvcRequestMatcher(introspector, "/swagger-ui/**");
        MvcRequestMatcher swaggerDocsMatcher = new MvcRequestMatcher(introspector, "/docs/**");
        AntPathRequestMatcher postFormMatcher = new AntPathRequestMatcher("/v1/form", "POST");
         MvcRequestMatcher paymentPostMatcher = new MvcRequestMatcher(introspector, "/v1/payment/");
         MvcRequestMatcher formUpdateMatcher = new MvcRequestMatcher(introspector, "/v1/form/form-update/*");
         MvcRequestMatcher formMatcherReview = new MvcRequestMatcher(introspector, "/v1/form/rating-review/*");
         MvcRequestMatcher formMatcherScreenShot = new MvcRequestMatcher(introspector, "/v1/form/add-screenshot/*");
         MvcRequestMatcher formMatcherGetMood = new MvcRequestMatcher(introspector, "/v1/mood/get-AllMood-Active");
         MvcRequestMatcher formMatcherGetInstrument = new MvcRequestMatcher(introspector, "/v1/instrument/get-AllInstrument-Active");
         MvcRequestMatcher formMatcherGetLanguage = new MvcRequestMatcher(introspector, "/v1/language/get-AllLanguage-Active");
         MvcRequestMatcher orderSummaryMatcher = new MvcRequestMatcher(introspector, "/v1/orderSummary/**");
         MvcRequestMatcher filedMatcher = new MvcRequestMatcher(introspector, "/v1/Filed/**");
         MvcRequestMatcher ArtistMatcher = new MvcRequestMatcher(introspector, "/v1/artistmaster/**");
         MvcRequestMatcher MixturetMatcher = new MvcRequestMatcher(introspector, "/v1/mixturemaster/**");
         MvcRequestMatcher DeliveryMatcher = new MvcRequestMatcher(introspector, "/v1/deliveryDate/**");
         AntPathRequestMatcher FormGetMatcher = new AntPathRequestMatcher("/v1/form/{id}","GET");
         MvcRequestMatcher upiGetImage = new MvcRequestMatcher(introspector, "/v1/payment/upi/*");
         AntPathRequestMatcher getDeliveryPayment =new AntPathRequestMatcher("/v1/payment/calculatedeliverypayment","GET");
         AntPathRequestMatcher getDeliveryMatcher = new AntPathRequestMatcher("/v1/form/","GET");
         AntPathRequestMatcher getOrderTrackerMatcher = new AntPathRequestMatcher("/v1/form/*","GET");
         MvcRequestMatcher getSongFile = new MvcRequestMatcher(introspector,"/v1/form/song/*");
         MvcRequestMatcher getSongFileForMail = new MvcRequestMatcher(introspector,"/v1/form/songDownload/*");
         MvcRequestMatcher addCommentMatcher = new MvcRequestMatcher(introspector,"/v1/form/add-comment/*");
         MvcRequestMatcher getTrackerMatcher = new MvcRequestMatcher(introspector,"/v1/form/orderTracker/");
         MvcRequestMatcher getUserMatcher = new MvcRequestMatcher(introspector,"/v1/users/**");
         MvcRequestMatcher getInstaPosts = new MvcRequestMatcher(introspector,"/v1/instaIntegration/**");
         MvcRequestMatcher getContactMatcher = new MvcRequestMatcher(introspector,"/v1/form/contactus");
		 MvcRequestMatcher getLoginMatcher = new MvcRequestMatcher(introspector, "/v1/authentication/**");
		 MvcRequestMatcher createPaymentOrderMatcher = new MvcRequestMatcher(introspector,"/v1/masterpayment/createOrder");
		 MvcRequestMatcher handlePaymentOrderMatcher = new MvcRequestMatcher(introspector,"/v1/masterpayment/handle");
		 MvcRequestMatcher sendOtpMatcher = new MvcRequestMatcher(introspector, "/v1/form/send-otp");
		 MvcRequestMatcher verifyOtpMatcher = new MvcRequestMatcher(introspector, "/v1/form/verify-otp");
		 MvcRequestMatcher resendyOtpMatcher = new MvcRequestMatcher(introspector, "/v1/form/resend-otp");
		 MvcRequestMatcher validateNumberMatcher = new MvcRequestMatcher(introspector,"/v1/form/validatemobilenumber/**");
		 MvcRequestMatcher instrumentImagesMatcher = new MvcRequestMatcher(introspector, "/v1/instrument/instrumentimage/*");
		 MvcRequestMatcher allInstrumentImagesMatcher = new MvcRequestMatcher(introspector, "/v1/instrument/getallinsrumentimages");
		 MvcRequestMatcher getWelcomeVideosMatcher = new MvcRequestMatcher(introspector,"/v1/welcomeVideo/getAllWelcomeVideos");
	     MvcRequestMatcher fetchWelcomeVideosMatcher = new MvcRequestMatcher(introspector, "/v1/welcomeVideo/video/**");
	     MvcRequestMatcher getWelcomeVideosMobile = new MvcRequestMatcher(introspector,"/v1/welcomeVideo/getMobileWelcomeVideo");

		http
				.csrf(csrf -> csrf.disable())
				.cors(cors -> Customizer.withDefaults())
				.authorizeHttpRequests(authorize -> authorize
						  .requestMatchers(postFormMatcher).permitAll()
		                    .requestMatchers(formUpdateMatcher).permitAll()
		                    .requestMatchers(formMatcherGetMood).permitAll()
		                    .requestMatchers(formMatcherGetInstrument).permitAll()
		                    .requestMatchers(formMatcherGetLanguage).permitAll()
		                    .requestMatchers(formMatcherReview).permitAll()
		                    .requestMatchers(formMatcherScreenShot).permitAll()
		                    .requestMatchers(paymentPostMatcher).permitAll()
		                    .requestMatchers(orderSummaryMatcher).permitAll()
		                    .requestMatchers(swaggerUIDefaultMatcher).permitAll()
		                    .requestMatchers(swaggerUIMatcher).permitAll()
		                    .requestMatchers(swaggerDocsMatcher).permitAll()
		                    .requestMatchers(filedMatcher).permitAll()
		                    .requestMatchers(upiGetImage).permitAll()
		                    .requestMatchers(ArtistMatcher).permitAll()
		                    .requestMatchers(DeliveryMatcher).permitAll()
		                    .requestMatchers(FormGetMatcher).permitAll()
		                    .requestMatchers(getDeliveryMatcher).permitAll()
		                    .requestMatchers(getDeliveryPayment).permitAll()
		                    .requestMatchers(getSongFile).permitAll()
		                    .requestMatchers(getTrackerMatcher).permitAll()
		                    .requestMatchers(getUserMatcher).permitAll()
		                    .requestMatchers(getOrderTrackerMatcher).permitAll()
		                    .requestMatchers(getInstaPosts).permitAll()
		                    .requestMatchers(getContactMatcher).permitAll()
							.requestMatchers(getLoginMatcher).permitAll()
							.requestMatchers(createPaymentOrderMatcher).permitAll()
							.requestMatchers(handlePaymentOrderMatcher).permitAll()
							.requestMatchers(sendOtpMatcher).permitAll()
							.requestMatchers(verifyOtpMatcher).permitAll()
							.requestMatchers(resendyOtpMatcher).permitAll()
							.requestMatchers(validateNumberMatcher).permitAll()
							.requestMatchers(instrumentImagesMatcher).permitAll()
							.requestMatchers(allInstrumentImagesMatcher).permitAll()
							.requestMatchers(getWelcomeVideosMatcher).permitAll()
							.requestMatchers(fetchWelcomeVideosMatcher).permitAll()
							.requestMatchers(getSongFileForMail).permitAll()
							.requestMatchers(getWelcomeVideosMobile).permitAll()
		                    .requestMatchers(MixturetMatcher).permitAll()
		                    
						.anyRequest().authenticated())
				.exceptionHandling(exception -> exception
		                .accessDeniedHandler(accessDeniedHandler())  // Custom handler for AccessDeniedException
		                .authenticationEntryPoint((AuthenticationEntryPoint) new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED))  // Default entry point for other exceptions
		            )
				.oauth2ResourceServer(oauth2 -> oauth2.jwt(jwt -> jwt.decoder(jwtDecoder())))
				.exceptionHandling(exception -> exception.authenticationEntryPoint(entryPoint));
		return http.build();
		
//		MvcRequestMatcher swaggerUIMatcher = new MvcRequestMatcher(introspector, "/ui");
//		MvcRequestMatcher swaggerUIDefaultMatcher = new MvcRequestMatcher(introspector, "/swagger-ui/**");
//		MvcRequestMatcher swaggerDocsMatcher = new MvcRequestMatcher(introspector, "/docs/**");
//		AntPathRequestMatcher postFormMatcher = new AntPathRequestMatcher("/v1/form", "POST");
//		 MvcRequestMatcher paymentPostMatcher = new MvcRequestMatcher(introspector, "/v1/payment/");
//		 MvcRequestMatcher formUpdateMatcher = new MvcRequestMatcher(introspector, "/v1/form/form-update/*");
//		 MvcRequestMatcher formMatcherReview = new MvcRequestMatcher(introspector, "/v1/form/rating-review/*");
//		 MvcRequestMatcher formMatcherScreenShot = new MvcRequestMatcher(introspector, "/v1/form/add-screenshot/*");
//		 MvcRequestMatcher formMatcherGetMood = new MvcRequestMatcher(introspector, "/v1/mood/*");
//		 MvcRequestMatcher formMatcherGetInstrument = new MvcRequestMatcher(introspector, "/v1/instrument/*");
//		 MvcRequestMatcher formMatcherGetLanguage = new MvcRequestMatcher(introspector, "/v1/language/*");
//		 MvcRequestMatcher orderSummaryMatcher = new MvcRequestMatcher(introspector, "/v1/orderSummary/**");
//		 MvcRequestMatcher filedMatcher = new MvcRequestMatcher(introspector, "/v1/Filed/**");
		 //MvcRequestMatcher upiGetImage = new MvcRequestMatcher(introspector, "/v1/payment/upi/*");
//		 
//
//	        http
//	            .csrf(csrf -> csrf.disable())
//	            .cors(cors -> Customizer.withDefaults())
//	            .authorizeHttpRequests(authorize -> authorize
//	                .requestMatchers(postFormMatcher).permitAll()
		 
//	                .requestMatchers(formUpdateMatcher).permitAll()
//	                .requestMatchers(formMatcherGetMood).permitAll()
//	                .requestMatchers(formMatcherGetInstrument).permitAll()
//	                .requestMatchers(formMatcherGetLanguage).permitAll()
//	                .requestMatchers(formMatcherReview).permitAll()
//	                .requestMatchers(formMatcherScreenShot).permitAll()
//	                .requestMatchers(paymentPostMatcher).permitAll()
//	                .requestMatchers(orderSummaryMatcher).permitAll()
//	                .requestMatchers(swaggerUIDefaultMatcher).permitAll()
//	                .requestMatchers(swaggerUIMatcher).permitAll()
//	                .requestMatchers(swaggerDocsMatcher).permitAll()
//	                .requestMatchers(filedMatcher).permitAll()
//	                .anyRequest().authenticated()
//	            )
//	            .oauth2ResourceServer(oauth2 -> oauth2.jwt(jwt -> jwt.decoder(jwtDecoder())))
//	            .exceptionHandling(exception -> exception.authenticationEntryPoint(entryPoint));
//
//	        return http.build();
	}

	@Bean
	JwtDecoder jwtDecoder() {

		byte[] keyBytes = Decoders.BASE64
				.decode("9j7WszeA5eprDq2cFWYwRlK2oFz3xjHTGdyTzrRJVsRfPxPyWVa7wMvBn4nN9HLe");
		return NimbusJwtDecoder.withSecretKey(Keys.hmacShaKeyFor(keyBytes)).macAlgorithm(MacAlgorithm.HS256).build();
	}
	@Bean
    public AccessDeniedHandler accessDeniedHandler() {
        return (httpServletRequest, httpServletResponse, e) -> {
            httpServletResponse.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
            httpServletResponse.setContentType("application/json");
            httpServletResponse.getWriter().write("{\"status\": false, \"message\": \"Unauthorized\", \"errorType\": \"NONE\", \"timestamp\": " + System.currentTimeMillis() + "}");
        };
    }

}
	