package com.cameleer.server.app.analytics;

import com.cameleer.server.core.analytics.UsageEvent;
import com.cameleer.server.core.analytics.UsageTracker;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.servlet.HandlerInterceptor;

import java.time.Instant;
import java.util.regex.Pattern;

/**
 * Tracks authenticated UI user requests for usage analytics.
 * Skips agent requests, health checks, data ingestion, and static assets.
 */
public class UsageTrackingInterceptor implements HandlerInterceptor {

    private static final String START_ATTR = "usage.startNanos";

    // Patterns for normalizing dynamic path segments
    private static final Pattern EXCHANGE_ID = Pattern.compile(
            "/[A-F0-9]{15,}-[A-F0-9]{16}(?=/|$)", Pattern.CASE_INSENSITIVE);
    private static final Pattern UUID = Pattern.compile(
            "/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}(?=/|$)", Pattern.CASE_INSENSITIVE);
    private static final Pattern HEX_HASH = Pattern.compile(
            "/[0-9a-f]{32,64}(?=/|$)", Pattern.CASE_INSENSITIVE);
    private static final Pattern NUMERIC_ID = Pattern.compile(
            "(?<=/)(\\d{2,})(?=/|$)");
    // Agent instance IDs like "cameleer-sample-598867949d-g7nt4-1"
    private static final Pattern INSTANCE_ID = Pattern.compile(
            "(?<=/agents/)[^/]+(?=/)", Pattern.CASE_INSENSITIVE);

    private final UsageTracker usageTracker;

    public UsageTrackingInterceptor(UsageTracker usageTracker) {
        this.usageTracker = usageTracker;
    }

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        request.setAttribute(START_ATTR, System.nanoTime());
        return true;
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response,
                                 Object handler, Exception ex) {
        String username = extractUsername();
        if (username == null) return; // unauthenticated or agent request

        Long startNanos = (Long) request.getAttribute(START_ATTR);
        long durationMs = startNanos != null ? (System.nanoTime() - startNanos) / 1_000_000 : 0;

        String path = request.getRequestURI();
        String queryString = request.getQueryString();

        usageTracker.track(new UsageEvent(
                Instant.now(),
                username,
                request.getMethod(),
                path,
                normalizePath(path),
                response.getStatus(),
                durationMs,
                queryString
        ));
    }

    private String extractUsername() {
        Authentication auth = SecurityContextHolder.getContext().getAuthentication();
        if (auth == null || auth.getName() == null) return null;
        String name = auth.getName();
        // Only track UI users (user:admin), not agents
        if (!name.startsWith("user:")) return null;
        return name;
    }

    static String normalizePath(String path) {
        String normalized = EXCHANGE_ID.matcher(path).replaceAll("/{id}");
        normalized = UUID.matcher(normalized).replaceAll("/{id}");
        normalized = HEX_HASH.matcher(normalized).replaceAll("/{hash}");
        normalized = INSTANCE_ID.matcher(normalized).replaceAll("{id}");
        normalized = NUMERIC_ID.matcher(normalized).replaceAll("{id}");
        return normalized;
    }
}
