package admin

import (
	"context"
	"time"

	"sogoms.com/internal/protocol"
)

// AuditEvent représente un type d'événement audit.
type AuditEvent string

// Événements audit.
const (
	AuditLoginSuccess   AuditEvent = "login_success"
	AuditLoginFailed    AuditEvent = "login_failed"
	AuditLogout         AuditEvent = "logout"
	AuditSessionExpired AuditEvent = "session_expired"
	AuditActionPerformed AuditEvent = "action_performed"
	AuditPermissionDenied AuditEvent = "permission_denied"
)

// AuditLogger enregistre les événements admin vers sogoms-logs.
type AuditLogger struct {
	logsPool *protocol.Pool
	appID    string // "admin" pour les logs admin
}

// NewAuditLogger crée un nouveau logger d'audit.
func NewAuditLogger(logsPool *protocol.Pool) *AuditLogger {
	return &AuditLogger{
		logsPool: logsPool,
		appID:    "admin",
	}
}

// Log enregistre un événement d'audit (non-bloquant).
func (a *AuditLogger) Log(event AuditEvent, username string, data map[string]any) {
	if a.logsPool == nil {
		return
	}

	if data == nil {
		data = make(map[string]any)
	}
	data["username"] = username
	data["event"] = string(event)
	data["timestamp"] = time.Now().Format(time.RFC3339)

	go func() {
		ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
		defer cancel()

		req := protocol.NewRequest("log_event", map[string]any{
			"app_id":     a.appID,
			"event_type": "audit_" + string(event),
			"data":       data,
		})
		a.logsPool.Call(ctx, req)
	}()
}

// LogLogin enregistre une tentative de connexion.
func (a *AuditLogger) LogLogin(success bool, username, ip, userAgent string, reason string) {
	event := AuditLoginSuccess
	if !success {
		event = AuditLoginFailed
	}

	data := map[string]any{
		"ip":         ip,
		"user_agent": userAgent,
	}
	if reason != "" {
		data["reason"] = reason
	}

	a.Log(event, username, data)
}

// LogLogout enregistre une déconnexion.
func (a *AuditLogger) LogLogout(username, ip string) {
	a.Log(AuditLogout, username, map[string]any{
		"ip": ip,
	})
}

// LogAction enregistre une action effectuée.
func (a *AuditLogger) LogAction(username, action, appID string, details map[string]any) {
	data := map[string]any{
		"action":  action,
		"app_id":  appID,
		"details": details,
	}
	a.Log(AuditActionPerformed, username, data)
}

// LogPermissionDenied enregistre un refus de permission.
func (a *AuditLogger) LogPermissionDenied(username, action, appID, permission string) {
	a.Log(AuditPermissionDenied, username, map[string]any{
		"action":     action,
		"app_id":     appID,
		"permission": permission,
	})
}
