package ru.serega6531.packmate.security;

import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpHeaders;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import ru.serega6531.packmate.model.enums.FakeAdminMode;
import ru.serega6531.packmate.properties.PackmateProperties;

import java.io.IOException;
import java.util.Optional;

@Slf4j
@RequiredArgsConstructor
@Component
public class FakeAdminAuthFilter extends OncePerRequestFilter {

    private final PackmateProperties properties;

    @Override
    protected boolean shouldNotFilter(HttpServletRequest request) {
        if (!isFakeEnabled()) {
            return true;
        }

        String path = request.getRequestURI();
        return path.startsWith("/fake-admin")
                || path.startsWith("/api/fake")
                || path.startsWith("/fake/")
                || path.equals("/favicon.ico");
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        if (!isFakeEnabled()) {
            filterChain.doFilter(request, response);
            return;
        }

        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        boolean isFakeAdmin = authentication != null && authentication.isAuthenticated()
                && authentication.getAuthorities().stream().anyMatch(a -> a.getAuthority().equals("ROLE_FAKE"));

        if (isFakeAdmin) {
            FakeAdminMode mode = Optional.ofNullable(properties.web().fakeAdmin())
                    .map(PackmateProperties.FakeAdminProperties::mode)
                    .orElse(FakeAdminMode.FUN);
            String target = "/fake-admin/" + resolvePath(mode);
            log.info("Redirecting fake admin to {}", target);
            response.setStatus(HttpServletResponse.SC_TEMPORARY_REDIRECT);
            response.setHeader(HttpHeaders.LOCATION, target);
            return;
        }

        filterChain.doFilter(request, response);
    }

    private boolean isFakeEnabled() {
        return Optional.ofNullable(properties.web().fakeAdmin())
                .map(PackmateProperties.FakeAdminProperties::enabled)
                .orElse(false);
    }

    private String resolvePath(FakeAdminMode mode) {
        return switch (mode) {
            case FAKE_PACKETS -> "packets";
            case FUN -> "fun";
        };
    }
}
