package handlers

import (
	"context"
	"encoding/json"
	"log"
	"net/http"

	"github.com/gin-gonic/gin"

	"switchboard-core/models"
	"switchboard-core/store"
)

// AuditLog writes an audit entry via the store interface.
// Non-blocking: errors are logged but don't break the caller.
func AuditLog(auditStore store.AuditStore, c *gin.Context, action, resourceType, resourceID string, metadata map[string]interface{}) {
	if auditStore == nil {
		return
	}

	actorID := getUserID(c)
	if actorID == "" {
		return
	}

	var meta models.JSONMap
	if metadata != nil {
		b, _ := json.Marshal(metadata)
		json.Unmarshal(b, &meta)
	}

	entry := &models.AuditEntry{
		ActorID:      &actorID,
		Action:       action,
		ResourceType: resourceType,
		ResourceID:   resourceID,
		Metadata:     meta,
		IPAddress:    c.ClientIP(),
		UserAgent:    c.GetHeader("User-Agent"),
	}

	if err := auditStore.Log(context.Background(), entry); err != nil {
		log.Printf("audit log error: %v", err)
	}
}

// ── Admin Audit Viewer ──────────────────────

// ListAuditLog returns paginated audit entries with optional filters.
// GET /api/v1/admin/audit?page=1&per_page=50&action=user.create&actor_id=...&resource_type=...
func (h *AdminHandler) ListAuditLog(c *gin.Context) {
	page, perPage, offset := parsePagination(c)

	opts := store.AuditListOptions{
		ListOptions: store.ListOptions{
			Limit:  perPage,
			Offset: offset,
		},
		Action:       c.Query("action"),
		ActorID:      c.Query("actor_id"),
		ResourceType: c.Query("resource_type"),
	}

	entries, total, err := h.stores.Audit.List(c.Request.Context(), opts)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "query failed"})
		return
	}
	if entries == nil {
		entries = []models.AuditEntry{}
	}

	c.JSON(http.StatusOK, gin.H{
		"data":     entries,
		"total":    total,
		"page":     page,
		"per_page": perPage,
	})
}

// ListAuditActions returns distinct action names for filter dropdowns.
// GET /api/v1/admin/audit/actions
func (h *AdminHandler) ListAuditActions(c *gin.Context) {
	actions, err := h.stores.Audit.ListActions(c.Request.Context())
	if err != nil {
		c.JSON(http.StatusOK, gin.H{"actions": []string{}})
		return
	}
	c.JSON(http.StatusOK, gin.H{"actions": actions})
}
