package logging

import (
	"fmt"
	"github.com/UpmeshLTD/urus-aio/infrastructure/config"

	"github.com/blendle/zapdriver"
	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
)

type zapDriverLogger struct {
	*zap.SugaredLogger
}

// NewZapDriverLogger returns a new instance of Logger that uses Zap & Stack Driver.
func NewZapDriverLogger(cp config.Provider) Logger {
	conf := GetConfig(cp)

	var zapConfig zap.Config
	if conf.IsDevelopment {
		// running in development mode we will use a human-readable output
		zapConfig = zapdriver.NewDevelopmentConfig()
		zapConfig.Encoding = "console"
		zapConfig.EncoderConfig.EncodeLevel = zapcore.CapitalColorLevelEncoder
	} else {
		zapConfig = zapdriver.NewProductionConfig()
		zapConfig.Level = zap.NewAtomicLevelAt(zap.DebugLevel)
	}

	var l zapcore.Level
	if err := l.UnmarshalText([]byte(conf.Level)); err != nil {
		l = zap.DebugLevel
	}
	zapConfig.Level = zap.NewAtomicLevelAt(l)

	clientLogger, err := zapConfig.Build()
	if err != nil {
		panic(fmt.Sprintf("zap.config.Build(): %v", err))
	}

	return &zapDriverLogger{
		clientLogger.Sugar(),
	}
}

func NewZapDriverLoggerV2(conf *Config) Logger {
	var zapConfig zap.Config
	if conf.IsDevelopment {
		// running in development mode we will use a human-readable output
		zapConfig = zapdriver.NewDevelopmentConfig()
		zapConfig.Encoding = "console"
		zapConfig.EncoderConfig.EncodeLevel = zapcore.CapitalColorLevelEncoder
	} else {
		zapConfig = zapdriver.NewProductionConfig()
		zapConfig.Level = zap.NewAtomicLevelAt(zap.DebugLevel)
	}

	var l zapcore.Level
	if err := l.UnmarshalText([]byte(conf.Level)); err != nil {
		l = zap.DebugLevel
	}
	zapConfig.Level = zap.NewAtomicLevelAt(l)

	clientLogger, err := zapConfig.Build()
	if err != nil {
		panic(fmt.Sprintf("zap.config.Build(): %v", err))
	}

	return &zapDriverLogger{
		clientLogger.Sugar(),
	}
}

// With returns a new logger with given arguments.
func (l *zapDriverLogger) With(args ...interface{}) Logger {
	return &zapDriverLogger{
		l.Desugar().Sugar().With(args...),
	}
}
