package com.honey.honey.security;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.honey.honey.model.UserA;
import com.honey.honey.service.LocalizationService;
import com.honey.honey.service.SessionService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.util.Map;
import java.util.Optional;

@Slf4j
@Component
@RequiredArgsConstructor
public class AuthInterceptor implements HandlerInterceptor {

    private final SessionService sessionService;
    private final LocalizationService localizationService;
    private final ObjectMapper objectMapper = new ObjectMapper();

    @Override
    public boolean preHandle(HttpServletRequest req, HttpServletResponse res, Object handler) {

        // Allow CORS preflight (OPTIONS) without auth
        if ("OPTIONS".equalsIgnoreCase(req.getMethod())) {
            return true;
        }

        // Get Bearer token from Authorization header
        String authHeader = req.getHeader("Authorization");
        String sessionId = extractBearerToken(authHeader);

        // If no Bearer token, fail
        if (sessionId == null || sessionId.isBlank()) {
            log.debug("Missing Bearer token");
            res.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
            return false;
        }

        // Validate session and get user
        Optional<UserA> userOpt = sessionService.getUserBySession(sessionId);

        if (userOpt.isEmpty()) {
            log.debug("Invalid or expired session: {}", maskSessionId(sessionId));
            res.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
            return false;
        }

        UserA user = userOpt.get();
        if (user.getBanned() != null && user.getBanned() == 1) {
            log.debug("Banned user attempted access: userId={}", user.getId());
            res.setStatus(HttpServletResponse.SC_FORBIDDEN);
            res.setContentType("application/json");
            res.setCharacterEncoding("UTF-8");
            try {
                String message = localizationService.getMessageForUser(user.getId(), "auth.error.accessRestricted");
                String body = objectMapper.writeValueAsString(Map.of("code", "BANNED", "message", message));
                res.getWriter().write(body);
            } catch (Exception e) {
                log.warn("Failed to write banned response body", e);
            }
            return false;
        }

        // Put user in context
        UserContext.set(user);

        return true;
    }

    /**
     * Extracts Bearer token from Authorization header.
     */
    private String extractBearerToken(String authHeader) {
        if (authHeader != null && authHeader.startsWith("Bearer ")) {
            return authHeader.substring(7).trim();
        }
        return null;
    }

    /**
     * Masks session ID for logging (security).
     */
    private String maskSessionId(String sessionId) {
        if (sessionId == null || sessionId.length() < 8) {
            return "***";
        }
        return sessionId.substring(0, 4) + "***" + sessionId.substring(sessionId.length() - 4);
    }

    @Override
    public void afterCompletion(HttpServletRequest req, HttpServletResponse res, Object handler, Exception ex) {
        UserContext.clear();
    }
}

