package com.rera.mss.security

import org.springframework.security.authentication.UsernamePasswordAuthenticationToken
import org.springframework.security.core.context.SecurityContextHolder
import org.springframework.security.core.userdetails.UserDetails
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource
import org.springframework.web.filter.OncePerRequestFilter
import java.net.InetAddress
import java.time.Instant
import javax.servlet.FilterChain
import javax.servlet.http.HttpServletRequest
import javax.servlet.http.HttpServletResponse


class JwtAuthenticationFilter(
        private val tokenProvider: JwtTokenProvider,
        private val customUserDetailsService: CustomUserDetailsService
) : OncePerRequestFilter() {

    override fun doFilterInternal(request: HttpServletRequest, response: HttpServletResponse, filterChain: FilterChain) {
        try {
            val timestamp = Instant.now().toEpochMilli()
            val ip = InetAddress.getLocalHost().hostAddress
            logger.info("timestamp=${timestamp},remoteAddress=${request.remoteAddr},ip=${ip},method=${request.method},path=${request.requestURI}")


            val jwt: String? = getJwtFromRequest(request)

            if (!jwt.isNullOrBlank() && tokenProvider.validateToken(jwt)) {
                val userId: Long = tokenProvider.getUserIdFromJwt(jwt)
                val userDetails: UserDetails = customUserDetailsService.loadUserById(userId)
                val authentication = UsernamePasswordAuthenticationToken(userDetails, null, userDetails.authorities)
                authentication.details = WebAuthenticationDetailsSource().buildDetails(request)
                SecurityContextHolder.getContext().authentication = authentication
            }
        } catch (e: Exception) {
            logger.error("Could not set user authentication in security context", e)
        }
        filterChain.doFilter(request, response)
    }

    private fun getJwtFromRequest(request: HttpServletRequest): String? {
        val bearerToken = request.getHeader("Authorization")
        if (!(bearerToken.isNullOrBlank() || !bearerToken.startsWith("Bearer"))) {
            return bearerToken.substring(7, bearerToken.length)
        }
        return null
    }
}