package store

import (
	"fmt"
	"strings"
)

// EventLogFilter holds optional filters for listing event log entries.
type EventLogFilter struct {
	Severity string // Filter by severity (info, warn, error).
	Source   string // Filter by source.
	Since    string // Only events created at or after this timestamp.
	Until    string // Only events created at or before this timestamp.
	Limit    int    // Maximum number of results (default 50).
	Offset   int    // Offset for pagination.
}

// EventLogStats holds counts of event log entries by severity.
type EventLogStats struct {
	Info  int `json:"info"`
	Warn  int `json:"warn"`
	Error int `json:"error"`
	Total int `json:"total"`
}

// InsertEvent inserts a new event log entry.
func (s *Store) InsertEvent(evt EventLog) (EventLog, error) {
	evt.CreatedAt = Now()
	if evt.Metadata == "" {
		evt.Metadata = "{}"
	}

	result, err := s.db.Exec(
		`INSERT INTO event_log (source, severity, message, metadata, created_at)
		 VALUES (?, ?, ?, ?, ?)`,
		evt.Source, evt.Severity, evt.Message, evt.Metadata, evt.CreatedAt,
	)
	if err != nil {
		return EventLog{}, fmt.Errorf("insert event: %w", err)
	}

	id, err := result.LastInsertId()
	if err != nil {
		return EventLog{}, fmt.Errorf("get event id: %w", err)
	}
	evt.ID = id

	return evt, nil
}

// ListEvents returns event log entries matching the given filter.
func (s *Store) ListEvents(filter EventLogFilter) ([]EventLog, error) {
	var conditions []string
	var args []any

	if filter.Severity != "" {
		parts := strings.Split(filter.Severity, ",")
		if len(parts) == 1 {
			conditions = append(conditions, "severity = ?")
			args = append(args, filter.Severity)
		} else {
			placeholders := make([]string, len(parts))
			for i, p := range parts {
				placeholders[i] = "?"
				args = append(args, strings.TrimSpace(p))
			}
			conditions = append(conditions, "severity IN ("+strings.Join(placeholders, ",")+")")
		}
	}
	if filter.Source != "" {
		parts := strings.Split(filter.Source, ",")
		if len(parts) == 1 {
			conditions = append(conditions, "source = ?")
			args = append(args, filter.Source)
		} else {
			placeholders := make([]string, len(parts))
			for i, p := range parts {
				placeholders[i] = "?"
				args = append(args, strings.TrimSpace(p))
			}
			conditions = append(conditions, "source IN ("+strings.Join(placeholders, ",")+")")
		}
	}
	if filter.Since != "" {
		conditions = append(conditions, "created_at >= ?")
		args = append(args, filter.Since)
	}
	if filter.Until != "" {
		conditions = append(conditions, "created_at <= ?")
		args = append(args, filter.Until)
	}

	query := "SELECT id, source, severity, message, metadata, created_at FROM event_log"
	if len(conditions) > 0 {
		query += " WHERE " + strings.Join(conditions, " AND ")
	}
	query += " ORDER BY created_at DESC"

	limit := filter.Limit
	if limit <= 0 {
		limit = 50
	}
	if limit > 500 {
		limit = 500
	}
	query += fmt.Sprintf(" LIMIT %d OFFSET %d", limit, filter.Offset)

	rows, err := s.db.Query(query, args...)
	if err != nil {
		return nil, fmt.Errorf("query events: %w", err)
	}
	defer rows.Close()

	events := []EventLog{}
	for rows.Next() {
		var evt EventLog
		if err := rows.Scan(&evt.ID, &evt.Source, &evt.Severity, &evt.Message, &evt.Metadata, &evt.CreatedAt); err != nil {
			return nil, fmt.Errorf("scan event: %w", err)
		}
		events = append(events, evt)
	}
	return events, rows.Err()
}

// GetEventStats returns counts of event log entries grouped by severity.
func (s *Store) GetEventStats() (EventLogStats, error) {
	rows, err := s.db.Query(
		`SELECT severity, COUNT(*) FROM event_log GROUP BY severity`,
	)
	if err != nil {
		return EventLogStats{}, fmt.Errorf("query event stats: %w", err)
	}
	defer rows.Close()

	var stats EventLogStats
	for rows.Next() {
		var severity string
		var count int
		if err := rows.Scan(&severity, &count); err != nil {
			return EventLogStats{}, fmt.Errorf("scan event stats: %w", err)
		}
		switch severity {
		case "info":
			stats.Info = count
		case "warn":
			stats.Warn = count
		case "error":
			stats.Error = count
		}
		stats.Total += count
	}
	return stats, rows.Err()
}

// PruneEvents deletes event log entries older than the given number of days.
func (s *Store) PruneEvents(olderThanDays int) (int64, error) {
	if olderThanDays < 1 {
		return 0, fmt.Errorf("prune events: olderThanDays must be >= 1, got %d", olderThanDays)
	}
	result, err := s.db.Exec(
		`DELETE FROM event_log WHERE created_at < datetime('now', ?)`,
		fmt.Sprintf("-%d days", olderThanDays),
	)
	if err != nil {
		return 0, fmt.Errorf("prune events: %w", err)
	}
	return result.RowsAffected()
}
