package middleware

import (
	"log"
	"net/url"
	"strings"
	"time"

	"github.com/gin-gonic/gin"
)

var sensitiveQueryKeys = map[string]struct{}{
	"token":         {},
	"access_token":  {},
	"refresh_token": {},
	"code":          {},
	"secret":        {},
}

func Logger() gin.HandlerFunc {
	return func(c *gin.Context) {
		start := time.Now()
		path := c.Request.URL.Path
		raw := sanitizeQuery(c.Request.URL.RawQuery)

		c.Next()

		latency := time.Since(start)
		status := c.Writer.Status()
		method := c.Request.Method
		ip := c.ClientIP()
		userAgent := c.Request.UserAgent()
		userID, _ := c.Get("user_id")
		traceID := GetTraceID(c)

		log.Printf("[API] %s %s %s | status: %d | latency: %v | ip: %s | user_id: %v | trace_id: %s | ua: %s",
			time.Now().Format("2006-01-02 15:04:05"),
			method,
			path,
			status,
			latency,
			ip,
			userID,
			traceID,
			userAgent,
		)

		if len(c.Errors) > 0 {
			for _, err := range c.Errors {
				log.Printf("[Error] trace_id: %s | %v", traceID, err)
			}
		}

		if raw != "" {
			log.Printf("[Query] %s?%s", path, raw)
		}
	}
}

func sanitizeQuery(raw string) string {
	if raw == "" {
		return ""
	}

	values, err := url.ParseQuery(raw)
	if err != nil {
		return ""
	}

	for key := range values {
		if isSensitiveQueryKey(key) {
			values.Set(key, "***")
		}
	}

	return values.Encode()
}

func isSensitiveQueryKey(key string) bool {
	normalized := strings.ToLower(strings.TrimSpace(key))
	if _, ok := sensitiveQueryKeys[normalized]; ok {
		return true
	}
	return strings.Contains(normalized, "token") || strings.Contains(normalized, "secret")
}
