package com.handong.smartservice.JwtAuth;

import java.io.IOException;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.filter.OncePerRequestFilter;

import com.handong.smartservice._AG;
import com.handong.smartservice.component.UserInfo;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.JwtException;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

public class JwtAuthFilter extends OncePerRequestFilter {
    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    private final JwtProvider jwtProvider;


    public JwtAuthFilter(JwtProvider jwtProvider) {
        this.jwtProvider = jwtProvider;
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        String uri = request.getRequestURI();
        
        logger.info("doFilterInternal: " + uri);

        //if (uri.compareTo("/api/add-transaction.do") == 0 ||
        //    uri.compareTo("/api/sign-in.do") == 0 ||
        //    uri.compareTo("/api/sval2.do") == 0) {
        //    filterChain.doFilter(request, response);
        //    return;
        //}
        if (_AG.isSkipAuthUri(uri)) {
            filterChain.doFilter(request, response);
            return;
        }

        String auth = request.getHeader("Authorization");
        if (auth == null) {
            //logger.info("doFilterInternal: auth == null");
            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
            return;
        }

        if (auth != null && auth.startsWith("Bearer ")) {
            String token = auth.substring(7);
            if (token == null) {
                logger.info("doFilterInternal: token == null, req = " + uri);
                response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
                return;
            }
            
            try {
                Claims claims = jwtProvider.getClaims(token);

                //List<GrantedAuthority> authorities = List.of(new SimpleGrantedAuthority("ROLE_USER"));
                //UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(_AG.createJwtUserInfo(claims), authorities, List.of());
                UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(_AG.createJwtUserInfo(claims), null, List.of());

                SecurityContext context = SecurityContextHolder.createEmptyContext();
                context.setAuthentication(authentication);
                SecurityContextHolder.setContext(context);
            }
            catch (ExpiredJwtException e) {
                //e.printStackTrace();
                response.setStatus(HttpStatus.UNAUTHORIZED.value());
                return;
            }            
            catch (JwtException | IllegalArgumentException e) {
                //e.printStackTrace();
                logger.info("doFilterInternal, JWT validation failed, uri={}, msg={}", uri, e.getMessage());
                response.setStatus(HttpStatus.UNAUTHORIZED.value());
                return;
            }
        }

        filterChain.doFilter(request, response);
    }
}
