package com.social.media.infrastructure.config;

import java.util.Arrays;
import java.util.List;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

/**
 * CORS Configuration for cross-origin requests
 * Supports both development and production environments
 */
@Configuration
public class CorsConfig implements WebMvcConfigurer {

    @Value("${security.cors.allowed-origins:http://localhost:4200}")
    private String allowedOrigins;

    @Value("${security.cors.allowed-methods:GET,POST,PUT,DELETE,PATCH,OPTIONS}")
    private String allowedMethods;

    @Value("${security.cors.allowed-headers:*}")
    private String allowedHeaders;

    @Value("${security.cors.allow-credentials:true}")
    private boolean allowCredentials;

    @Value("${security.cors.max-age:3600}")
    private long maxAge;

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        // Parse allowed origins from comma-separated string
        List<String> originsList = Arrays.asList(allowedOrigins.split(","));
        String[] originsArray = originsList.toArray(new String[0]);
        
        // Parse allowed methods from comma-separated string
        String[] methodsArray = allowedMethods.split(",");
        
        // Parse allowed headers
        String[] headersArray;
        if ("*".equals(allowedHeaders)) {
            headersArray = new String[]{"*"};
        } else {
            headersArray = allowedHeaders.split(",");
        }
        
        registry.addMapping("/**")
                .allowedOriginPatterns(originsArray)
                .allowedMethods(methodsArray)
                .allowedHeaders(headersArray)
                .allowCredentials(allowCredentials)
                .maxAge(maxAge);
    }

    @Bean
    public CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration configuration = new CorsConfiguration();
        
        // Parse allowed origins from comma-separated string
        List<String> originsList = Arrays.asList(allowedOrigins.split(","));
        
        // Use allowedOriginPatterns instead of allowedOrigins when credentials are enabled
        if (allowCredentials) {
            configuration.setAllowedOriginPatterns(originsList);
        } else {
            configuration.setAllowedOrigins(originsList);
        }
        
        // Parse allowed methods from comma-separated string
        List<String> methodsList = Arrays.asList(allowedMethods.split(","));
        configuration.setAllowedMethods(methodsList);
        
        // Configure allowed headers
        if ("*".equals(allowedHeaders)) {
            configuration.setAllowedHeaders(Arrays.asList("*"));
        } else {
            List<String> headersList = Arrays.asList(allowedHeaders.split(","));
            configuration.setAllowedHeaders(headersList);
        }
        
        // Allow credentials (cookies, authorization headers)
        configuration.setAllowCredentials(allowCredentials);
        
        // How long the response from a pre-flight request can be cached
        configuration.setMaxAge(maxAge);
        
        // Headers that can be exposed to the client
        configuration.setExposedHeaders(Arrays.asList(
            "Authorization",
            "Content-Disposition",
            "Content-Type",
            "Content-Length",
            "X-Total-Count",
            "X-Total-Pages",
            "Cache-Control"
        ));

        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        
        return source;
    }
}
