package com.app.config.swagger;

import com.app.constant.JwtConstant;
import io.swagger.annotations.Api;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Profile;
import org.springframework.http.HttpHeaders;
import org.springframework.util.StopWatch;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.ParameterBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.schema.ModelRef;
import springfox.documentation.service.*;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.service.contexts.SecurityContext;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * 功能描述：SwaggerUI配置类
 *
 * @Auther: 梁展鹏
 * @Date: 2018/8/2 10:21
 */
@Slf4j
@Profile({"dev", "test"})
@EnableSwagger2
@SpringBootConfiguration
public class SwaggerUIConfig implements WebMvcConfigurer {

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("swagger-ui.html").addResourceLocations("classpath:/META-INF/resources/");
        registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
        registry.addResourceHandler("/web_frontend/**").addResourceLocations("classpath:/web_frontend/");
    }

    /**
     * 功能描述：客户端接口API
     *
     * @return
     * @Auther: 梁展鹏
     * @Date: 2018/8/2 10:21
     */
    @Bean
    public Docket frontEndUIAPI() {
        StopWatch watch = new StopWatch();
        watch.start();

        List<Parameter> list = Arrays.asList(
                new ParameterBuilder()
                        .name(HttpHeaders.AUTHORIZATION)
                        .description(HttpHeaders.AUTHORIZATION)
                        .modelRef(new ModelRef("string"))
                        .parameterType("header")
                        .defaultValue(JwtConstant.PREFIX_HEADER_NAME + JwtConstant.TEST_TOKEN_VALUE)
                        .required(Boolean.FALSE)
                        .build()
        );
        Docket docket = new Docket(DocumentationType.SWAGGER_2)
                .groupName("客户端接口 - 微信小程序") // 定义组
                .apiInfo(apiInfo()) // 配置说明
                .securitySchemes(securitySchemes())
                .securityContexts(securityContexts())
                .ignoredParameterTypes(HttpServletRequest.class) // 方法参数忽略，例如HttpServletRequest不想展示在Swagger上
                .select() // 选中哪些路径和api会生成Document
                .apis(RequestHandlerSelectors.withClassAnnotation(Api.class)) // 拦截的包路径
                .paths(PathSelectors.regex("(/api/.*)|(/common/.*)")) // 拦截的接口路径
                .build(); // 创建

        watch.stop();
        log.info("Started Swagger(客户端接口API) in [{}] ms", watch.getTotalTimeMillis());

        return docket;
    }

    /**
     * 功能描述：管理后台界面接口API
     *
     * @return
     * @Auther: 梁展鹏
     * @Date: 2018/8/2 10:21
     */
    @Bean
    public Docket backEndWebUIAPI() {
        StopWatch watch = new StopWatch();
        watch.start();

        List<Parameter> list = Arrays.asList(
                new ParameterBuilder()
                        .name(HttpHeaders.AUTHORIZATION)
                        .description(HttpHeaders.AUTHORIZATION)
                        .modelRef(new ModelRef("string"))
                        .parameterType("header")
                        .defaultValue(JwtConstant.PREFIX_HEADER_NAME + JwtConstant.TEST_TOKEN_VALUE)
                        .required(Boolean.FALSE)
                        .build()
        );
        Docket docket = new Docket(DocumentationType.SWAGGER_2)
                .groupName("Web管理后台") // 定义组
                .apiInfo(apiInfo()) // 配置说明
                .securitySchemes(securitySchemes())
                .securityContexts(securityContexts())
                .globalOperationParameters(list)
                .ignoredParameterTypes(HttpServletRequest.class) // 方法参数忽略，例如HttpServletRequest不想展示在Swagger上
                .select() // 选中哪些路径和api会生成Document
                .apis(RequestHandlerSelectors.withClassAnnotation(Api.class)) // 拦截的包路径
                .paths(PathSelectors.regex("(/admin/.*)|(/common/.*)")) // 拦截的接口路径
                .build(); // 创建

        watch.stop();
        log.info("Started Swagger(管理后台界面接口API) in [{}] ms", watch.getTotalTimeMillis());

        return docket;
    }

    /**
     * 功能描述：平台管理
     *
     * @return
     * @Auther: 梁展鹏
     * @Date: 2018/8/2 10:21
     */
    @Bean
    public Docket backEndPlatformWebUIAPI() {
        StopWatch watch = new StopWatch();
        watch.start();

        List<Parameter> list = Arrays.asList(
                new ParameterBuilder()
                        .name(HttpHeaders.AUTHORIZATION)
                        .description(HttpHeaders.AUTHORIZATION)
                        .modelRef(new ModelRef("string"))
                        .parameterType("header")
                        .defaultValue(JwtConstant.PREFIX_HEADER_NAME + JwtConstant.TEST_TOKEN_VALUE)
                        .required(Boolean.FALSE)
                        .build()
        );
        Docket docket = new Docket(DocumentationType.SWAGGER_2)
                .groupName("Web管理后台 - 平台管理") // 定义组
                .apiInfo(apiInfo()) // 配置说明
                .securitySchemes(securitySchemes())
                .securityContexts(securityContexts())
                .globalOperationParameters(list)
                .ignoredParameterTypes(HttpServletRequest.class) // 方法参数忽略，例如HttpServletRequest不想展示在Swagger上
                .select() // 选中哪些路径和api会生成Document
                .apis(RequestHandlerSelectors.withClassAnnotation(Api.class)) // 拦截的包路径
                .paths(PathSelectors.regex("(/platform/.*)")) // 拦截的接口路径
                .build(); // 创建

        watch.stop();
        log.info("Started Swagger(管理后台界面接口API) in [{}] ms", watch.getTotalTimeMillis());

        return docket;
    }

    private List<ApiKey> securitySchemes() {
        List<ApiKey> apiKeyList = new ArrayList<>();
        apiKeyList.add(new ApiKey("token", "token", "header"));
        return apiKeyList;
    }

    private List<SecurityContext> securityContexts() {
        List<SecurityContext> securityContexts = new ArrayList<>();
        securityContexts.add(SecurityContext
                .builder()
                .securityReferences(defaultAuth())
                .forPaths(PathSelectors.regex("^(?!auth).*$"))
                .build());
        return securityContexts;
    }

    private List<SecurityReference> defaultAuth() {
        AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything");
        AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
        authorizationScopes[0] = authorizationScope;
        List<SecurityReference> securityReferences = new ArrayList<>();
        securityReferences.add(new SecurityReference("token", authorizationScopes));
        return securityReferences;
    }

    /**
     * 功能描述：SwaggerUI文档的基本信息
     *
     * @return
     * @Auther: 梁展鹏
     * @Date: 2018/8/2 10:21
     */
    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                .title("430平台")
                .description("430平台")
                .termsOfServiceUrl("")
                .contact(new Contact("梁展鹏", "http://127.0.0.1", "fsliangzp@163.com"))
                .version("v0.0.1")
                .build();
    }

}
