package middlewares

import (
	"bssapp-backend/auth"
	"bssapp-backend/internal/auditlog"
	"log"
	"net"
	"net/http"
	"strings"
	"time"
)

type statusWriter struct {
	http.ResponseWriter
	status int
}

func (w *statusWriter) WriteHeader(code int) {
	w.status = code
	w.ResponseWriter.WriteHeader(code)
}

func RequestLogger(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {

		start := time.Now()

		sw := &statusWriter{
			ResponseWriter: w,
			status:         200,
		}

		// ---------- CLAIMS ----------
		claims, _ := auth.GetClaimsFromContext(r.Context())

		// ---------- IP ----------
		ip := r.RemoteAddr
		if host, _, err := net.SplitHostPort(ip); err == nil {
			ip = host
		}

		// ---------- UA ----------
		ua := r.UserAgent()

		// ---------- SESSION ----------
		sessionID := ""
		if claims != nil {
			sessionID = claims.SessionID
		}

		hasAuth := r.Header.Get("Authorization") != ""

		log.Printf("➡️  %s %s | auth=%v", r.Method, r.URL.Path, hasAuth)

		// ---------- RUN ----------
		next.ServeHTTP(sw, r)

		finish := time.Now()
		dur := int(finish.Sub(start).Milliseconds())

		log.Printf("⬅️  %s %s | status=%d | %s", r.Method, r.URL.Path, sw.status, time.Since(start))

		// High-frequency endpoints: skip route_access audit to reduce DB/log pressure.
		skipAudit := r.Method == http.MethodGet && strings.HasPrefix(r.URL.Path, "/api/product-images")

		// ---------- AUDIT (route_access) ----------
		al := auditlog.ActivityLog{
			ActionType:     "route_access",
			ActionCategory: "nav",
			ActionTarget:   r.URL.Path,
			Description:    r.Method + " " + r.URL.Path,

			IpAddress: ip,
			UserAgent: ua,
			SessionID: sessionID,

			RequestStartedAt:  start,
			RequestFinishedAt: finish,
			DurationMs:        dur,
			HttpStatus:        sw.status,

			IsSuccess: sw.status < 400,
		}

		// ---------- CLAIMS → LOG ----------
		if claims != nil {
			al.Username = claims.Username
			al.RoleCode = claims.RoleCode
			al.DfUsrID = int64(claims.ID)

			// Eğer claims içinde UUID varsa ekle (sende varsa aç)
			// al.UserID = claims.UserUUID
		} else {
			al.RoleCode = "public"
		}

		// ---------- ERROR ----------
		if sw.status >= 400 {
			al.ErrorMessage = http.StatusText(sw.status)
		}

		if !skipAudit {
			auditlog.Enqueue(r.Context(), al)
		}

		if claims == nil {
			log.Println("⚠️ LOGGER: claims is NIL")
		} else {
			log.Printf("✅ LOGGER CLAIMS user=%s role=%s id=%d", claims.Username, claims.RoleCode, claims.ID)
		}
	})
}
