package middleware

import (
	"encoding/json"
	"github.com/gofiber/fiber/v2"
	"gorm.io/gorm"
	"log"
	"netidhub-saas-be/app/database/entity"
	utilSvc "netidhub-saas-be/utils/service"
	"strings"
	"time"
)

func AuditTrailsMiddleware(db *gorm.DB) fiber.Handler {
	return func(c *fiber.Ctx) error {
		start := time.Now()
		requestBody := c.Body()

		headersMap := c.GetReqHeaders()
		headersJSON, _ := json.Marshal(headersMap)

		authHeader := c.Get("Authorization")
		userId := utilSvc.GetUserId(authHeader)

		err := c.Next()

		audit := entity.AuditTrails{
			Method:         c.Method(),
			Path:           c.OriginalURL(),
			IP:             getIP(c),
			Status:         c.Response().StatusCode(),
			UserID:         userId,
			RequestHeaders: string(headersJSON),
			RequestBody:    string(requestBody),
			ResponseBody:   string(c.Response().Body()),
			DurationMs:     time.Since(start).Milliseconds(),
			CreatedAt:      time.Now(),
		}

		go db.Create(&audit)

		return err
	}
}

func StartAuditTrailCleanup(db *gorm.DB, retention int) {
	go func() {
		for {
			time.Sleep(24 * time.Hour)

			cutoff := time.Now().AddDate(0, 0, retention)
			db.Where("created_at < ?", cutoff).Delete(&entity.AuditTrails{})

			log.Printf(" at: %s", cutoff)
		}
	}()
}

func getIP(c *fiber.Ctx) string {
	ip := c.Get("X-Forwarded-For")
	if ip == "" {
		ip = c.IP()
	}
	if strings.Contains(ip, ":") {
		ip = strings.Split(ip, ":")[0]
	}
	return ip
}
