package middleware

import (
	"fmt"
	"strings"
	"system-altrak/internal/domain"
	actModule "system-altrak/internal/modules/activity"

	"github.com/gofiber/fiber/v2"
	"gorm.io/gorm"
)

// ActivityLogMiddleware mencatat aktivitas pengguna secara mendalam ke database
func ActivityLogMiddleware(db *gorm.DB) fiber.Handler {
	return func(c *fiber.Ctx) error {
		// Simpan data request sebelum dieksekusi jika perlu
		method := c.Method()
		path := c.Path()
		
		// Jalankan handler berikutnya
		err := c.Next()

		// Filter request yang tidak perlu dicatat (misalnya health check, dashboard refresh rutin jika terlalu bising)
		if strings.Contains(path, "/health") || strings.Contains(path, "/activities/dashboard") {
			return err
		}

		// Ambil data identitas dari locals
		userID, _ := c.Locals("user_id").(uint)
		username, _ := c.Locals("username").(string)
		role, _ := c.Locals("role").(string)
		branchID, _ := c.Locals("current_branch_id").(uint)

		// Tentukan modul dan aksi
		moduleKey := actModule.ResolveModuleKeyFromPath(path)
		action := actModule.ResolveActionLabel(method, path)

		// Detail default
		details := fmt.Sprintf("%s %s -> HTTP %d", method, path, c.Response().StatusCode())

		// Jika ini adalah operasi perubahan (POST/PUT/PATCH/DELETE), coba ambil detail lebih dalam
		if method != "GET" && method != "HEAD" && method != "OPTIONS" {
			body := c.Body()
			if len(body) > 0 {
				// Trim body jika terlalu panjang agar tidak memenuhi DB
				bodyStr := string(body)
				// Mask password for security
				if strings.Contains(bodyStr, "\"password\"") {
					bodyStr = "HIDDEN (SENSITIVE DATA)"
				} else if len(bodyStr) > 500 {
					bodyStr = bodyStr[:500] + "..."
				}
				details = fmt.Sprintf("%s | Body: %s", details, bodyStr)
			}
		}

		// Logika khusus untuk ekspor yang biasanya menggunakan GET
		if method == "GET" && (strings.Contains(path, "/export") || strings.Contains(path, "/pdf")) {
			action = "EXPORT"
		}

		ip := c.IP()
		if c.Get("X-Forwarded-For") != "" {
			ip = strings.Split(c.Get("X-Forwarded-For"), ",")[0]
		}

		logEntry := &domain.ActivityLog{
			UserID:    userID,
			Username:  username,
			Role:      role,
			Module:    moduleKey,
			Action:    action,
			Details:   strings.TrimSpace(details),
			IPAddress: ip,
			UserAgent: c.Get("User-Agent"),
			BranchID:  branchID,
		}

		// Simpan log secara asinkron agar tidak memperlambat response
		go func(l *domain.ActivityLog) {
			_ = db.Create(l).Error
		}(logEntry)

		return err
	}
}
