package com.petshop.backend.config;

import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletRequestWrapper;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import java.io.IOException;

@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class TrailingSlashNormalizationFilter extends OncePerRequestFilter {

    @Override
    protected boolean shouldNotFilter(HttpServletRequest request) {
        String requestUri = request.getRequestURI();
        if (requestUri == null || requestUri.isBlank()) {
            return true;
        }
        return requestUri.equals(normalizePath(requestUri));
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        String normalizedUri = normalizePath(request.getRequestURI());
        String normalizedServletPath = normalizePath(request.getServletPath());
        String normalizedPathInfo = normalizePath(request.getPathInfo());

        HttpServletRequestWrapper wrapper = new HttpServletRequestWrapper(request) {
            @Override
            public String getRequestURI() {
                return normalizedUri;
            }

            @Override
            public StringBuffer getRequestURL() {
                String original = super.getRequestURL().toString();
                int schemeSeparator = original.indexOf("://");
                int pathStart = schemeSeparator >= 0 ? original.indexOf('/', schemeSeparator + 3) : original.indexOf('/');
                if (pathStart < 0) {
                    return new StringBuffer(original);
                }
                String prefix = original.substring(0, pathStart);
                return new StringBuffer(prefix + normalizedUri);
            }

            @Override
            public String getServletPath() {
                return normalizedServletPath;
            }

            @Override
            public String getPathInfo() {
                return normalizedPathInfo;
            }
        };

        filterChain.doFilter(wrapper, response);
    }

    private String normalizePath(String value) {
        if (value == null) {
            return null;
        }
        String normalized = value.replace('\\', '/');
        while (normalized.contains("//")) {
            normalized = normalized.replace("//", "/");
        }
        if (shouldLowercase(normalized)) {
            normalized = normalized.toLowerCase(java.util.Locale.ROOT);
        }
        int end = normalized.length();
        while (end > 1 && normalized.charAt(end - 1) == '/') {
            end--;
        }
        return normalized.substring(0, end);
    }

    private boolean shouldLowercase(String path) {
        String lower = path.toLowerCase(java.util.Locale.ROOT);
        return lower.startsWith("/api/")
                || lower.equals("/api")
                || lower.startsWith("/ws/")
                || lower.equals("/ws");
    }
}
