package io.delphiplatform.api.config;

import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.format.FormatterRegistry;
import org.springframework.retry.annotation.EnableRetry;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import io.delphiplatform.api.v3.view.interceptor.UnknownParamsHandlerInterceptor;

@EnableRetry
@Configuration
public class WebConfig implements WebMvcConfigurer {

    private final UnknownParamsHandlerInterceptor unknownParamsHandlerInterceptor;

    public WebConfig(
        UnknownParamsHandlerInterceptor unknownParamsHandlerInterceptor) {
        this.unknownParamsHandlerInterceptor = unknownParamsHandlerInterceptor;
    }

    @Override
    public void addFormatters(FormatterRegistry registry) {
        registry.addConverter(new AggByEnumConverter());
        registry.addConverter(new DataHealthBreakdownEnumConverter());
        registry.addConverter(new DataHealthBreakdownGroupEnumConverter());
        registry.addConverter(new CoreDataHealthStatusEnumConverter());
        registry.addConverter(new ChartTrackMetricsDimensionEnumConverter());
        registry.addConverter(new AdsDataHealthStatusEnumConverter());
        registry.addConverter(new SpotifyDataHealthStatusEnumConverter());
        registry.addConverter(new AppleMusicDataHealthStatusEnumConverter());
        registry.addConverter(new AmazonDataHealthStatusEnumConverter());
        registry.addConverter(new TikTokBreakdownEnumConverter());
        registry.addConverter(new TikTokContentTypeEnumConverter());
        registry.addConverter(new TikTokChartTypeEnumConverter());
        registry.addConverter(new TikTokStateMetricEnumConverter());
        registry.addConverter(new TikTokTopAnalyticMetricEnumConverter());
        registry.addConverter(new VideoDspSlugEnumConverter());
        registry.addConverter(new VideoChartGroupEnumConverter());
        registry.addConverter(new IncludeVideoChartEnumConverter());
        registry.addConverter(new YouTubeContentTypeEnumConverter());
        registry.addConverter(new YouTubeMetricsCategoryEnumConverter());
        registry.addConverter(new ExpandToEnumConverter());
        registry.addConverter(new GroupByEnumConverter());
        registry.addConverter(new GroupByAdsPerformanceEnumConverter());
        registry.addConverter(new TrackGroupByFieldEnumConverter());
        registry.addConverter(new GroupByFieldEnumConverter());
        registry.addConverter(new GroupByVideoEnumConverter());
        registry.addConverter(new IncludeTracksEnumConverter());
        registry.addConverter(new IncludeStreamsEnumConverter());
        registry.addConverter(new IncludeTracklistChartEnumConverter());
        registry.addConverter(new IncludeTracklistPlaylistEnumConverter());
        registry.addConverter(new IndexParamEnumConverter());
        registry.addConverter(new SortOrderEnumConverter());
        registry.addConverter(new SubsetParamEnumConverter());
        registry.addConverter(new AdsDspSlugEnumConverter());
        registry.addConverter(new TrackMediaTypeEnumConverter());
        registry.addConverter(new IncludeChartEnumConverter());
        registry.addConverter(new TikTokMetricsEnumConverter());
        registry.addConverter(new SpotifyChartTypeEnumConverter());
        registry.addConverter(new TrackStateIncludesEnumConverter());
        registry.addConverter(new ChartTrackStateIncludesEnumConverter());
        registry.addConverter(new SpotifyChartBreakdownEnumConverter());
        registry.addConverter(new AnalyticsMetricsEnumConverter());
        registry.addConverter(new PeriodDaysWeeksEnumConverter());
        registry.addConverter(new JunoSpotifyStreamsIncludesEnumConverter());
        registry.addConverter(new TikTokTopIsrcVideoTopByEnumConverter());
    }

    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/health").setViewName("forward:/actuator/health");
        registry.addViewController("/v2/health").setViewName("forward:/actuator/health");
        registry.addViewController("/v2/ui/").setViewName(
            "redirect:/api-docs/swagger-ui/index.html?configUrl=/v3/api-docs/swagger-config&urls.primaryName=v2");
        registry.addViewController("/v3/ui/").setViewName(
            "redirect:/api-docs/swagger-ui/index.html?configUrl=/v3/api-docs/swagger-config&urls.primaryName=v3");
        registry.addRedirectViewController("/v2/ui", "/v2/ui/");
        registry.addRedirectViewController("/v3/ui", "/v3/ui/");
    }

    @Bean
    public ConfigurableServletWebServerFactory webServerFactory() {
        TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory();
        factory.addConnectorCustomizers(connector -> {
            // allow backslashes and query characters used by elasticsearch
            connector.setProperty("relaxedQueryChars", "\\|{}[]<>~^");
        });
        return factory;
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(unknownParamsHandlerInterceptor);
    }
}
