package logging

import (
	"context"
	"log/slog"
)

type ExportHandlerConfig struct {
	MinLevel   slog.Level // Only export logs for this min log level.
	BufferSize int        // Logs channel size.
}

func NewExportHandler(cfg ExportHandlerConfig) *ExportHandler {
	if cfg.BufferSize == 0 {
		cfg.BufferSize = 1000
	}

	handler := &ExportHandler{
		cfg: cfg,
		ch:  make(chan slog.Record, cfg.BufferSize),
	}
	return handler
}

// ExportHandler exports logs to separate channel available via Records()
type ExportHandler struct {
	next slog.Handler
	cfg  ExportHandlerConfig

	ch chan slog.Record
}

func (h *ExportHandler) Register(next slog.Handler) slog.Handler {
	h.next = next
	return h
}

func (h *ExportHandler) Records() <-chan slog.Record {
	return h.ch
}

func (h *ExportHandler) Enabled(ctx context.Context, level slog.Level) bool {
	if h.next == nil {
		return true
	}
	return h.next.Enabled(ctx, level)
}

func (h *ExportHandler) Handle(ctx context.Context, record slog.Record) error {
	if record.Level >= h.cfg.MinLevel {
		select {
		case <-ctx.Done():
			return ctx.Err()
		case h.ch <- record:
		default:
		}
	}
	if h.next == nil {
		return nil
	}
	return h.next.Handle(ctx, record)
}

func (h *ExportHandler) WithAttrs(attrs []slog.Attr) slog.Handler {
	clone := &ExportHandler{
		cfg: h.cfg,
		ch:  h.ch,
	}
	if h.next != nil {
		clone.next = h.next.WithAttrs(attrs)
	}
	return clone
}

func (h *ExportHandler) WithGroup(name string) slog.Handler {
	clone := &ExportHandler{
		cfg: h.cfg,
		ch:  h.ch,
	}
	if h.next != nil {
		clone.next = h.next.WithGroup(name)
	}
	return clone
}