package audit

import (
	"context"
	"encoding/json"
	"fmt"
	"log/slog"
	"time"

	"github.com/jmoiron/sqlx"

	"github.com/tidbcloud/alertstore/pkg/jsonutil"
)

type Entry struct {
	ID        int64                       `db:"id" json:"id"`
	AlertID   string                      `db:"alert_id" json:"alert_id"`
	Event     string                      `db:"event" json:"event"`
	OldState  string                      `db:"old_state" json:"old_state"`
	NewState  string                      `db:"new_state" json:"new_state"`
	Actor     string                      `db:"actor" json:"actor"`
	Source    string                      `db:"source" json:"source"`
	Detail    jsonutil.NullableRawMessage `db:"detail" json:"detail" swaggertype:"object"`
	CreatedAt time.Time                   `db:"created_at" json:"created_at"`
}

type Store struct {
	db     *sqlx.DB
	logger *slog.Logger
}

func NewStore(db *sqlx.DB, logger *slog.Logger) *Store {
	return &Store{db: db, logger: logger}
}

func (s *Store) Log(ctx context.Context, alertID, event, oldState, newState, actor, source string, detail map[string]interface{}) {
	var detailJSON json.RawMessage
	if detail != nil {
		b, err := json.Marshal(detail)
		if err != nil {
			s.logger.Error("marshal audit detail", "err", err)
			return
		}
		detailJSON = b
	}

	const q = `
		INSERT INTO alert_audit (alert_id, event, old_state, new_state, actor, source, detail)
		VALUES (?, ?, ?, ?, ?, ?, ?)
	`
	_, err := s.db.ExecContext(ctx, q, alertID, event, oldState, newState, actor, source, detailJSON)
	if err != nil {
		s.logger.Error("insert audit entry", "err", err, "alert_id", alertID, "event", event)
	}
}

func (s *Store) ListByAlertID(ctx context.Context, alertID string) ([]Entry, error) {
	const q = `SELECT * FROM alert_audit WHERE alert_id = ? ORDER BY created_at ASC`
	var entries []Entry
	if err := s.db.SelectContext(ctx, &entries, q, alertID); err != nil {
		return nil, fmt.Errorf("list audit: %w", err)
	}
	return entries, nil
}
