package log

import (
	"context"
	"jirasop/pkg/infra/config"

	"github.com/go-logr/logr"
	"github.com/go-logr/zapr"
	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
)

var (
	Logger logr.Logger = logr.Discard()
)

func InitLogger(conf *config.LogConfig) error {
	cfg := zap.NewProductionConfig()

	cfg.Level = zap.NewAtomicLevelAt(zapcore.Level(-1 * conf.Level))
	cfg.Development = true
	cfg.Encoding = "console"
	cfg.EncoderConfig.EncodeTime = zapcore.RFC3339TimeEncoder
	cfg.EncoderConfig.EncodeLevel = zapcore.CapitalLevelEncoder
	opts := []zap.Option{}

	zapLog, err := cfg.Build(opts...)
	if err != nil {
		return err
	}

	Logger = zapr.NewLogger(zapLog)
	return nil
}

// NewContext returns a new Context, derived from ctx, which carries the
// provided Logger.
// It is same as `logr.NewContext`.
func NewContext(ctx context.Context, logger logr.Logger, keysAndValues ...interface{}) context.Context {
	return logr.NewContext(ctx, logger.WithValues(keysAndValues...))
}

// FromContextOrDef returns a Logger from ctx.  If no Logger is found, this
// returns the default Logger.
//
// `logr.FromContextOrDiscard` may return a zero logger, it is not we want.
func FromContextOrDef(ctx context.Context, def logr.Logger, keysAndValues ...interface{}) logr.Logger {
	logger := logr.FromContextOrDiscard(ctx)
	if logger.IsZero() {
		logger = def
	}

	return logger.WithValues(keysAndValues...)
}

// FromContext returns a Logger from ctx.  If no Logger is found, this
// returns the global Logger.
//
// `logr.FromContextOrDiscard` may return a zero logger, it is not we want.
func FromContext(ctx context.Context, keysAndValues ...interface{}) logr.Logger {
	return FromContextOrDef(ctx, Logger, keysAndValues...)
}
