package closer

import (
	"context"
	"errors"
	"fmt"
	"sync/atomic"

	"git.optclblast.xyz/draincloud/draincloud-core/internal/logger"
)

var globalCloser *Closer = &Closer{
	closeFns: make([]func() error, 0),
}

type Closer struct {
	_lock    atomic.Bool
	closeFns []func() error
}

func (c *Closer) Add(fn func() error) {
	if c._lock.Load() {
		return
	}
	c.closeFns = append(c.closeFns, fn)
}

func (c *Closer) Close() error {
	if !c._lock.CompareAndSwap(false, true) {
		return fmt.Errorf("already closed")
	}

	var commonErr error
	for _, fn := range c.closeFns {
		if err := fn(); err != nil {
			logger.Error(context.Background(), "[closer][Close] error at close func call", logger.Err(err))
			commonErr = errors.Join(commonErr, err)
		}
	}

	return commonErr
}

func Add(fn func() error) {
	globalCloser.Add(fn)
}

func Close() error {
	return globalCloser.Close()
}
