package logging

import (
	"errors"
	"io"
	"time"
)

// Logger is the logger abstraction. It largely follows logrus/zap structure.
//go:generate mockery --name=Logger --case=snake
type Logger interface {
	// Error creates a log entry that includes a Key/ErrorValue pair.
	Error(args ...interface{})
	// Warn creates a log entry that includes a Key/WarnValue pair.
	Warn(args ...interface{})
	// Info creates a log entry that includes a Key/InfoValue pair.
	Info(args ...interface{})
	// Debug creates a log entry that includes a Key/DebugValue pair.
	Debug(args ...interface{})

	// Errorw creates a log entry that includes a Key/ErrorValue pair.
	Errorw(msg string, args ...interface{})
	// Warnw creates a log entry that includes a Key/WarnValue pair.
	Warnw(msg string, args ...interface{})
	// Infow creates a log entry that includes a Key/InfoValue pair.
	Infow(msg string, args ...interface{})
	// Debugw creates a log entry that includes a Key/DebugValue pair.
	Debugw(msg string, args ...interface{})

	Errorf(format string, args ...interface{})
	Warnf(format string, args ...interface{})
	Infof(format string, args ...interface{})
	Debugf(format string, args ...interface{})

	// With returns a new Logger with given args as default Key/Value pairs.
	With(args ...interface{}) Logger
}

type LoggerConfig struct {
	Level         string
	Colorized     bool
	CloudWatchLog *CloudWatchLogConfig
}

type CloudWatchLogConfig struct {
	Region         string
	GroupName      string
	StreamName     string
	BatchFrequency time.Duration
}

var writer *io.Writer

func Writer() *io.Writer {
	return writer
}

func keyValuePairs(args ...interface{}) (map[string]interface{}, error) {
	n := len(args)
	if n > 0 && n%2 == 0 {
		data := map[string]interface{}{}
		for i := 0; i < n-1; i += 2 {
			key, val := args[i], args[i+1]
			if err, ok := val.(error); ok {
				val = err.Error()
			}
			if keyStr, ok := key.(string); ok {
				data[keyStr] = val
			} else {
				return nil, errors.New("invalid args")
			}
		}
		return data, nil
	}
	return nil, errors.New("invalid args")
}
