// Package audit provides tamper-evident audit logging with hash chaining
package audit

import (
	"context"
	"fmt"
	"time"
)

// TamperAlert represents a tampering detection event
type TamperAlert struct {
	DetectedAt   time.Time `json:"detected_at"`
	Severity     string    `json:"severity"` // "critical", "warning"
	Description  string    `json:"description"`
	ExpectedHash string    `json:"expected_hash,omitempty"`
	ActualHash   string    `json:"actual_hash,omitempty"`
	FilePath     string    `json:"file_path,omitempty"`
}

// AlertManager defines the interface for tamper alerting
type AlertManager interface {
	Alert(ctx context.Context, a TamperAlert) error
}

// LoggingAlerter logs alerts to a standard logger
type LoggingAlerter struct {
	logger interface {
		Error(msg string, keysAndValues ...any)
		Warn(msg string, keysAndValues ...any)
	}
}

// NewLoggingAlerter creates a new logging alerter
func NewLoggingAlerter(logger interface {
	Error(msg string, keysAndValues ...any)
	Warn(msg string, keysAndValues ...any)
}) *LoggingAlerter {
	return &LoggingAlerter{logger: logger}
}

// Alert logs the tamper alert
func (l *LoggingAlerter) Alert(_ context.Context, a TamperAlert) error {
	if l.logger == nil {
		return nil
	}

	if a.Severity == "critical" {
		l.logger.Error("TAMPERING DETECTED",
			"description", a.Description,
			"expected_hash", a.ExpectedHash,
			"actual_hash", a.ActualHash,
			"file_path", a.FilePath,
			"detected_at", a.DetectedAt,
		)
	} else {
		l.logger.Warn("Potential tampering detected",
			"description", a.Description,
			"expected_hash", a.ExpectedHash,
			"actual_hash", a.ActualHash,
			"file_path", a.FilePath,
			"detected_at", a.DetectedAt,
		)
	}
	return nil
}

// MultiAlerter sends alerts to multiple backends
type MultiAlerter struct {
	alerters []AlertManager
}

// NewMultiAlerter creates a new multi-alerter
func NewMultiAlerter(alerters ...AlertManager) *MultiAlerter {
	return &MultiAlerter{alerters: alerters}
}

// Alert sends alert to all configured alerters
func (m *MultiAlerter) Alert(ctx context.Context, a TamperAlert) error {
	var errs []error
	for _, alerter := range m.alerters {
		if err := alerter.Alert(ctx, a); err != nil {
			errs = append(errs, err)
		}
	}
	if len(errs) > 0 {
		return fmt.Errorf("alert failures: %v", errs)
	}
	return nil
}
