package cclotus.cloud.gateway

import cclotus.cloud.gateway.domain.TimeResult
import cclotus.weixin.api.WxApiConfiguration
import gaf3.core.cloud.GafCloudConfiguration
import gaf3.core.gateway.filter.factory.JwtParserGatewayFilterFactory
import org.slf4j.LoggerFactory
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
import org.springframework.boot.autoconfigure.security.reactive.ReactiveSecurityAutoConfiguration
import org.springframework.boot.autoconfigure.security.reactive.ReactiveUserDetailsServiceAutoConfiguration
import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration
import org.springframework.boot.autoconfigure.security.servlet.UserDetailsServiceAutoConfiguration
import org.springframework.boot.context.event.ApplicationStartedEvent
import org.springframework.boot.runApplication
import org.springframework.cloud.gateway.support.ServerWebExchangeUtils
import org.springframework.cloud.openfeign.EnableFeignClients
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Import
import org.springframework.context.event.EventListener
import org.springframework.core.annotation.Order
import org.springframework.http.HttpStatus
import org.springframework.stereotype.Controller
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.ResponseBody
import org.springframework.web.server.WebFilter
import javax.annotation.PreDestroy


@SpringBootApplication(
    exclude = [SecurityAutoConfiguration::class,
        UserDetailsServiceAutoConfiguration::class,
        ReactiveSecurityAutoConfiguration::class,
        ReactiveUserDetailsServiceAutoConfiguration::class, DataSourceAutoConfiguration::class]
)
@Controller
@Import(GafCloudConfiguration::class, WxApiConfiguration::class)
@EnableFeignClients
open class AllInOneApplication {

    @GetMapping("/api/time")
    @ResponseBody
    fun getTime(): TimeResult {
        return TimeResult(System.currentTimeMillis())
    }

    @EventListener
    fun onStarted(event: ApplicationStartedEvent) {
        LoggerFactory.getLogger("Startup").info("系统启动成功!")
    }

    @PreDestroy
    fun onShutdown() {
        LoggerFactory.getLogger("Shutdown").info("系统正在关闭...")
    }

    @Bean
    @Order(-1)
    fun apiAccessFilter(): WebFilter {
        return WebFilter { exchange, chain ->
            val path = exchange.request.path.value()
            log.debug("[ApiAccess] path : {}", path)
            if (!path.startsWith("/api")
                    && !path.startsWith("/temp")
                    && !path.startsWith("/post")) {
                ServerWebExchangeUtils.setResponseStatus(exchange, HttpStatus.FORBIDDEN)
                exchange.response.setComplete()
            } else {
                chain.filter(exchange.mutate().build())
            }
        }
    }

    companion object {
        internal val log = LoggerFactory.getLogger(AllInOneApplication::class.java)
    }
}

fun main(args: Array<String>) {
    runApplication<AllInOneApplication>(*args)
    JwtParserGatewayFilterFactory.doInit()
}
