package auth

import (
	"context"
	"database/sql"
	"encoding/json"
	"net/http"
	"time"
)

// AuditWriter persists operator-significant events into the audit_log table
// created in Phase 0. Phase 2 writes register/login/logout/recovery rows.
// Subsequent phases will reuse the same table for destructive actions,
// emergency mode toggles, etc.
type AuditWriter struct {
	db *sql.DB
}

// NewAuditWriter wraps the *sql.DB.
func NewAuditWriter(db *sql.DB) *AuditWriter { return &AuditWriter{db: db} }

// Write records one audit row. actor is typically "operator"; for Phase 2's
// pre-auth ceremonies it's "anonymous". details is JSON-encoded into the
// details_json column.
func (a *AuditWriter) Write(ctx context.Context, r *http.Request, actor, action, targetType, targetID string, details map[string]any) {
	if a == nil || a.db == nil {
		return
	}
	var detailsJSON sql.NullString
	if len(details) > 0 {
		if b, err := json.Marshal(details); err == nil {
			detailsJSON = sql.NullString{String: string(b), Valid: true}
		}
	}
	var ua, ip sql.NullString
	if r != nil {
		if v := r.Header.Get("User-Agent"); v != "" {
			ua = sql.NullString{String: v, Valid: true}
		}
		if v := r.RemoteAddr; v != "" {
			ip = sql.NullString{String: v, Valid: true}
		}
	}
	_, _ = a.db.ExecContext(ctx, `
		INSERT INTO audit_log(timestamp, actor, action, target_type, target_id, details_json, ip_address, user_agent)
		VALUES (?, ?, ?, ?, ?, ?, ?, ?)
	`,
		time.Now().Unix(), actor, action,
		nullableText(targetType), nullableText(targetID),
		detailsJSON, ip, ua,
	)
}
