// Copyright The Monogon Project Authors.
// SPDX-License-Identifier: Apache-2.0

package logtree

import (
	"errors"
	"slices"
	"sync/atomic"

	"source.monogon.dev/go/logging"
)

type BacklogOrder int

const (
	BacklogOrderLatestFirst BacklogOrder = iota
	BacklogOrderOldestFirst
)

// LogReadOption describes options for the LogTree.Read call.
type LogReadOption func(*logReaderOptions)

type logReaderOptions struct {
	withChildren               bool
	withStream                 bool
	withBacklog                int
	withBacklogOrder           BacklogOrder
	onlyLeveled                bool
	onlyRaw                    bool
	leveledWithMinimumSeverity logging.Severity
	withStreamBufferSize       int
}

// WithChildren makes Read return/stream data for both a given DN and all its
// children.
func WithChildren() LogReadOption {
	return func(lro *logReaderOptions) {
		lro.withChildren = true
	}
}

// WithStream makes Read return a stream of data. This works alongside WithBacklog
// to create a read-and-stream construct.
func WithStream() LogReadOption {
	return func(lro *logReaderOptions) {
		lro.withStream = true
	}
}

// WithStreamBuffer applies WithStream and overrides the default stream buffer
// size of 128.
func WithStreamBuffer(size int) LogReadOption {
	return func(lro *logReaderOptions) {
		lro.withStreamBufferSize = size
		lro.withStream = true
	}
}

// WithBacklog makes Read return already recorded log entries, up to count
// elements.
func WithBacklog(count int) LogReadOption {
	return func(lro *logReaderOptions) { lro.withBacklog = count }
}

// WithBacklogOrder makes Read return log entries in the given order,
// default being latest messages first.
func WithBacklogOrder(order BacklogOrder) LogReadOption {
	return func(lro *logReaderOptions) { lro.withBacklogOrder = order }
}

// BacklogAllAvailable makes WithBacklog return all backlogged log data that
// logtree possesses.
const BacklogAllAvailable int = -1

func OnlyRaw() LogReadOption { return func(lro *logReaderOptions) { lro.onlyRaw = true } }

func OnlyLeveled() LogReadOption { return func(lro *logReaderOptions) { lro.onlyLeveled = true } }

// LeveledWithMinimumSeverity makes Read return only log entries that are at least
// at a given Severity. If only leveled entries are needed, OnlyLeveled must be
// used. This is a no-op when OnlyRaw is used.
func LeveledWithMinimumSeverity(s logging.Severity) LogReadOption {
	return func(lro *logReaderOptions) { lro.leveledWithMinimumSeverity = s }
}

// LogReader permits reading an already existing backlog of log entries and to
// stream further ones.
type LogReader struct {
	// Backlog are the log entries already logged by LogTree. This will only be set if
	// WithBacklog has been passed to Read.
	Backlog []*LogEntry
	// Stream is a channel of new entries as received live by LogTree. This will only
	// be set if WithStream has been passed to Read. In this case, entries from this
	// channel must be read as fast as possible by the consumer in order to prevent
	// missing entries.
	Stream <-chan *LogEntry
	// done is channel used to signal (by closing) that the log consumer is not
	// interested in more Stream data.
	done chan<- struct{}
	// missed is an atomic integer pointer that tells the subscriber how many messages
	// in Stream they missed. This pointer is nil if no streaming has been requested.
	missed *uint64
}

// Missed returns the amount of entries that were missed from Stream (as the
// channel was not drained fast enough).
func (l *LogReader) Missed() uint64 {
	// No Stream.
	if l.missed == nil {
		return 0
	}
	return atomic.LoadUint64(l.missed)
}

// Close closes the LogReader's Stream. This must be called once the Reader does
// not wish to receive streaming messages anymore.
func (l *LogReader) Close() {
	if l.done != nil {
		close(l.done)
	}
}

var (
	ErrRawAndLeveled = errors.New("cannot return logs that are simultaneously OnlyRaw and OnlyLeveled")
)

// Read and/or stream entries from a LogTree. The returned LogReader is influenced
// by the LogReadOptions passed, which influence whether the Read will return
// existing entries, a stream, or both. In addition the options also dictate
// whether only entries for that particular DN are returned, or for all sub-DNs as
// well.
func (l *LogTree) Read(dn DN, opts ...LogReadOption) (*LogReader, error) {
	l.journal.mu.RLock()
	defer l.journal.mu.RUnlock()

	lro := logReaderOptions{
		withStreamBufferSize: 128,
	}

	for _, opt := range opts {
		opt(&lro)
	}

	if lro.onlyLeveled && lro.onlyRaw {
		return nil, ErrRawAndLeveled
	}

	var filters []filter
	if lro.onlyLeveled {
		filters = append(filters, filterOnlyLeveled)
	}
	if lro.onlyRaw {
		filters = append(filters, filterOnlyRaw)
	}
	if lro.withChildren {
		filters = append(filters, filterSubtree(dn))
	} else {
		filters = append(filters, filterExact(dn))
	}
	if lro.leveledWithMinimumSeverity != "" {
		filters = append(filters, filterSeverity(lro.leveledWithMinimumSeverity))
	}

	var entries []*entry
	if lro.withBacklog > 0 || lro.withBacklog == BacklogAllAvailable {
		if lro.withChildren {
			entries = l.journal.scanEntries(lro.withBacklog, filters...)
		} else {
			entries = l.journal.getEntries(lro.withBacklog, dn, filters...)
		}
	}

	if lro.withBacklogOrder == BacklogOrderLatestFirst {
		// Reverse entries back into chronological order.
		slices.Reverse(entries)
	}

	lr := &LogReader{}
	if lro.withStream {
		sub := &subscriber{
			dataC:   make(chan *LogEntry, lro.withStreamBufferSize),
			doneC:   make(chan struct{}),
			filters: filters,
		}
		l.journal.subscribe(sub)

		lr.Stream = sub.dataC
		lr.done = sub.doneC
		lr.missed = &sub.missed
	}

	lr.Backlog = make([]*LogEntry, len(entries))
	for i, entry := range entries {
		lr.Backlog[i] = entry.external()
	}

	return lr, nil
}
