package com.kamco.cd.training.config.swagger;

import jakarta.servlet.http.HttpServletRequest;
import java.nio.charset.StandardCharsets;
import org.springdoc.core.properties.SwaggerUiConfigProperties;
import org.springdoc.core.properties.SwaggerUiOAuthProperties;
import org.springdoc.core.providers.ObjectMapperProvider;
import org.springdoc.webmvc.ui.SwaggerIndexPageTransformer;
import org.springdoc.webmvc.ui.SwaggerIndexTransformer;
import org.springdoc.webmvc.ui.SwaggerWelcomeCommon;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.context.annotation.Profile;
import org.springframework.core.io.Resource;
import org.springframework.web.servlet.resource.ResourceTransformerChain;
import org.springframework.web.servlet.resource.TransformedResource;

@Profile({"local", "dev"})
@Configuration
public class SwaggerUiAutoAuthConfig {

  @Bean
  @Primary
  public SwaggerIndexTransformer swaggerIndexTransformer(
      SwaggerUiConfigProperties swaggerUiConfigProperties,
      SwaggerUiOAuthProperties swaggerUiOAuthProperties,
      SwaggerWelcomeCommon swaggerWelcomeCommon,
      ObjectMapperProvider objectMapperProvider) {

    SwaggerIndexPageTransformer delegate =
        new SwaggerIndexPageTransformer(
            swaggerUiConfigProperties,
            swaggerUiOAuthProperties,
            swaggerWelcomeCommon,
            objectMapperProvider);

    return new SwaggerIndexTransformer() {
      private static final String TOKEN_KEY = "SWAGGER_ACCESS_TOKEN";

      @Override
      public Resource transform(
          HttpServletRequest request, Resource resource, ResourceTransformerChain chain) {
        try {
          // 1) springdoc 기본 변환 먼저 적용
          Resource transformed = delegate.transform(request, resource, chain);

          String html =
              new String(transformed.getInputStream().readAllBytes(), StandardCharsets.UTF_8);

          String loginPathContains = "/api/auth/signin";

          String inject =
              """
              tagsSorter: (a, b) => {
                      const TOP = '인증(Auth)';
                      if (a === TOP && b !== TOP) return -1;
                      if (b === TOP && a !== TOP) return 1;
                      return a.localeCompare(b);
                    },
            requestInterceptor: (req) => {
              const token = localStorage.getItem('%s');
              if (token) {
                req.headers = req.headers || {};
                req.headers['Authorization'] = 'Bearer ' + token;
              }
              return req;
            },
            responseInterceptor: async (res) => {
              try {
                const isLogin = (res?.url?.includes('%s') && res?.status === 200);
                if (isLogin) {
                  const text = (typeof res.data === 'string') ? res.data : JSON.stringify(res.data);
                  const json = JSON.parse(text);
                  const token = json?.data?.accessToken;

                  if (token) {
                    localStorage.setItem('%s', token);
                  }
                }
              } catch (e) {}
              return res;
            },
          """
                  .formatted(TOKEN_KEY, loginPathContains, TOKEN_KEY);

          html = html.replace("SwaggerUIBundle({", "SwaggerUIBundle({\n" + inject);

          return new TransformedResource(transformed, html.getBytes(StandardCharsets.UTF_8));
        } catch (Exception e) {
          // 실패 시 원본 반환(문서 깨짐 방지)
          return resource;
        }
      }
    };
  }
}
