package cloud.nstart.terravault.ordinis.restapi.config;

import io.swagger.v3.oas.models.Components;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Contact;
import io.swagger.v3.oas.models.info.Info;
import io.swagger.v3.oas.models.info.License;
import io.swagger.v3.oas.models.security.OAuthFlow;
import io.swagger.v3.oas.models.security.OAuthFlows;
import io.swagger.v3.oas.models.security.Scopes;
import io.swagger.v3.oas.models.security.SecurityRequirement;
import io.swagger.v3.oas.models.security.SecurityScheme;
import io.swagger.v3.oas.models.servers.Server;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.List;

/**
 * OpenAPI 3 spec для Swagger UI на {@code /swagger-ui.html}. Spec — на
 * {@code /v3/api-docs}.
 *
 * <p>Авторизация — JWT bearer от Keycloak ({@code auth.nstart.space}).
 * Service account для интеграторов (Альтум — {@code altum-backend}).
 */
@Configuration
public class OpenApiConfig {

  /** Keycloak issuer URI — base для auth/token endpoints. По умолчанию prod realm. */
  @Value("${ordinis.openapi.oauth.issuer-uri:https://auth.nstart.space/realms/nstart}")
  private String oauthIssuer;

  @Bean
  public OpenAPI ordinisOpenAPI() {
    String authUrl = oauthIssuer + "/protocol/openid-connect/auth";
    String tokenUrl = oauthIssuer + "/protocol/openid-connect/token";

    return new OpenAPI()
        .info(new Info()
            .title("Ordinis НСИ ЦУОД — Admin / Read API")
            .version("v1")
            .description("""
                MDM сервис для НСИ ЦУОД ОДХ.

                **Endpoints:**
                - `/api/v1/dictionaries` — справочники (admin write).
                - `/api/v1/dictionaries/{name}/records` — записи с bitemporal моделью.
                - `/api/v1/admin/audit` — журнал аудита (paginated + CSV export).
                - `/api/v1/admin/outbox` — статистика и DLQ.

                **Read-only API** (Альтум, геопортал, другие consumer'ы) — отдельный
                read-сервис на том же базовом URL: те же `GET /dictionaries/...`,
                но с поддержкой `?lang=ru/en` для flatten i18n и `?at=<iso>` для
                bitemporal queries.

                **Авторизация:**
                - **Try it out** в Swagger UI — нажми кнопку Authorize → выбери
                  "oauth2" → Keycloak login flow (PKCE, без client_secret).
                - **m2m интеграции** — service account через client_credentials
                  flow (см. /docs/integration/api/auth.html).

                **Полная интеграция:** https://ordinis.k8s.264.nstart.cloud/docs/
                """)
            .contact(new Contact()
                .name("Ordinis team")
                .email("zimin.an@nstart.space"))
            .license(new License().name("Internal").url("https://nstart.space")))
        .servers(List.of(
            new Server().url("https://ordinis.k8s.264.nstart.cloud").description("prod (cluster.142)"),
            new Server().url("https://ordinis.k8s.265.nstart.cloud").description("staging (cluster.265)"),
            new Server().url("http://localhost:8080").description("local dev")))
        .components(new Components()
            // Primary scheme: OAuth2 PKCE (для interactive Swagger UI users).
            // Keycloak realm `nstart`, public client `ordinis-swagger` с PKCE.
            .addSecuritySchemes("oauth2",
                new SecurityScheme()
                    .type(SecurityScheme.Type.OAUTH2)
                    .description("Keycloak OAuth2 — interactive login через Swagger UI с PKCE flow.")
                    .flows(new OAuthFlows()
                        .authorizationCode(new OAuthFlow()
                            .authorizationUrl(authUrl)
                            .tokenUrl(tokenUrl)
                            .scopes(new Scopes()
                                .addString("openid", "OIDC user profile")
                                .addString("profile", "User profile")
                                .addString("email", "Email")))))
            // Secondary scheme: pre-issued bearer token (для curl / scripts).
            .addSecuritySchemes("bearerAuth",
                new SecurityScheme()
                    .type(SecurityScheme.Type.HTTP)
                    .scheme("bearer")
                    .bearerFormat("JWT")
                    .description("Pre-issued JWT (например через client_credentials у service account).")))
        // Both schemes available — user picks one в Authorize dialog.
        .addSecurityItem(new SecurityRequirement().addList("oauth2"))
        .addSecurityItem(new SecurityRequirement().addList("bearerAuth"));
  }
}
