package com.psg.dlsysinfo.dl_sysinfo_server.security;

import com.psg.dlsysinfo.dl_sysinfo_server.service.UserService;
import io.jsonwebtoken.JwtException;
import io.jsonwebtoken.ExpiredJwtException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.web.filter.OncePerRequestFilter;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.security.core.userdetails.UsernameNotFoundException;


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

public class JwtAuthenticationFilter extends OncePerRequestFilter {


    private final UserService userService;
    private final JwtUtil jwtUtil;

    public JwtAuthenticationFilter(UserService userService, JwtUtil jwtUtil) {
        this.userService = userService;
        this.jwtUtil = jwtUtil;
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
            throws ServletException, IOException {

        String clientIp = extractClientIp(request);
        String uri = request.getRequestURI();
        System.out.println("🌐 Incoming request to " + uri + " from IP: " + clientIp);

        String jwt = null;

        // Try to get token from Authorization header
        String authHeader = request.getHeader("Authorization");
        if (authHeader != null && authHeader.startsWith("Bearer ")) {
            jwt = authHeader.substring(7);
            System.out.println("🔐 JWT found in Authorization header");
        }

        // If not in header, try cookie
        if (jwt == null && request.getCookies() != null) {
            for (jakarta.servlet.http.Cookie cookie : request.getCookies()) {
                if ("authToken".equals(cookie.getName())) {
                    jwt = cookie.getValue();
                    System.out.println("🍪 JWT extracted from authToken cookie");
                    break;
                }
            }
        }

        if (jwt == null) {
            System.out.println("🔓 No JWT found in header or cookie");
            chain.doFilter(request, response);
            return;
        }

        try {
            String username = jwtUtil.extractUsername(jwt);
            System.out.println("👤 Extracted username: " + username + " from IP: " + clientIp);

            if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
                UserDetails userDetails = userService.loadUserByUsername(username);

                if (jwtUtil.validateToken(jwt, username)) {
                    String displayName = jwtUtil.extractDisplayName(jwt);
                    String clientIdentifier = jwtUtil.extractClientIdentifier(jwt);
                    Long userId = jwtUtil.extractUserId(jwt);

                    List<String> roles = jwtUtil.extractRoles(jwt); // you’ll define this next

                    CurrentUser currentUser = new CurrentUser(
                            username,
                            displayName,
                            clientIdentifier,
                            userId,
                            roles
                    );



                    UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(
                            currentUser, null, userDetails.getAuthorities()
                    );

                    SecurityContextHolder.getContext().setAuthentication(authToken);
                    System.out.println("✅ Authenticated user: " + username + " from IP: " + clientIp);
                }
            }

        } catch (ExpiredJwtException e) {
            System.out.println("⏰ JWT expired from IP " + clientIp + ": " + e.getMessage());
            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
            response.setContentType("application/json");
            response.getWriter().write("{\"error\": \"Token expired\"}");
            return;

        } catch (JwtException | IllegalArgumentException e) {
            System.out.println("❌ Invalid JWT from IP " + clientIp + ": " + e.getMessage());
            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
            response.setContentType("application/json");
            response.getWriter().write("{\"error\": \"Invalid token\"}");
            return;

        } catch (UsernameNotFoundException e) {
            System.out.println("❌ User not found from IP " + clientIp + ": " + e.getMessage());
            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
            response.setContentType("application/json");
            response.getWriter().write("{\"error\": \"User not found\"}");
            return;
        }

        chain.doFilter(request, response);
    }


    private String extractClientIp(HttpServletRequest request) {
        String cfIp = request.getHeader("CF-Connecting-IP");
        if (cfIp != null && !cfIp.isEmpty()) return cfIp;

        String xfHeader = request.getHeader("X-Forwarded-For");
        if (xfHeader != null && !xfHeader.isEmpty()) {
            return xfHeader.split(",")[0].trim();
        }

        return request.getRemoteAddr();
    }



}