package matrix

import (
	"context"
	"fmt"
	"log/slog"
	"os"
	"sync/atomic"
)

type SlogHandler struct {
	slog.Handler

	writer slogWriter
}

func NewSlogHandler(opts *slog.HandlerOptions) *SlogHandler {
	handler := SlogHandler{}
	handler.Handler = slog.NewTextHandler(&handler.writer, opts)
	return &handler
}

func (sh *SlogHandler) Attach(bot *Bot) {
	sh.writer.matrix.Store(bot)
}

type slogWriter struct {
	matrix atomic.Pointer[Bot]
}

func (sw *slogWriter) Write(p []byte) (n int, err error) {
	matrixInstance := sw.matrix.Load()
	if matrixInstance == nil {
		// TODO: consider added a queue that we can drain when we get attached
		// to a Matrix instance.
		return
	}
	// Spawn a goroutine as not to make the code that initiated the log wait on us going over the network.
	go func() {
		if err := matrixInstance.sendInAdminRoom(context.TODO(), string(p)); err != nil {
			// Make sure not to use any logging method here that might feed back
			// into this function!
			fmt.Fprintf(os.Stderr, "failed to log message to admin room: %v\n", err)
		}
	}()
	return len(p), nil
}