package logger

import (
	// "path"
	"fmt"
	"net/http"
	"runtime"
	"strconv"
	"strings"
	"time"

	// "time"
	"github.com/gin-gonic/gin"
	rotatelogs "github.com/lestrrat-go/file-rotatelogs"
	"github.com/rifflock/lfshook"
	"github.com/sirupsen/logrus"
)

const filename = "./logs/console"

func init() {
	logrus.SetFormatter(&DFormatter{})
	writer, _ := rotatelogs.New(
		filename+".%Y%m%d.log",
		// rotatelogs.WithLinkName(filename),
		rotatelogs.WithRotationCount(50),
		rotatelogs.WithRotationTime(time.Hour*24),
	)
	logrus.AddHook(lfshook.NewHook(
		lfshook.WriterMap{
			logrus.DebugLevel: writer,
			logrus.InfoLevel:  writer,
			logrus.WarnLevel:  writer,
			logrus.ErrorLevel: writer,
			logrus.FatalLevel: writer,
			logrus.PanicLevel: writer,
		}, &logrus.TextFormatter{}),
	)

	// logrus.SetOutput(writer)
	// logrus.SetLevel(logrus.InfoLevel)
}

type DFormatter struct {
	TimestampFormat string
}

func (f *DFormatter) Format(entry *logrus.Entry) ([]byte, error) {
	timestampFormat := f.TimestampFormat
	if timestampFormat == "" {
		timestampFormat = "2006/01/02 15:04:05"
	}
	_, file, line, ok := runtime.Caller(9)
	if !ok {
		file = "???"
		line = 0
	}
	// _, filename := path.Split(file)
	msg := entry.Time.Format(timestampFormat) +
		" " + strings.ToUpper(entry.Level.String()) +
		" [" + file + ":" + strconv.Itoa(line) + "] " +
		entry.Message + "\n"

	return []byte(msg), nil
}

func Debugf(format string, args ...interface{}) {
	logrus.Debugf(format, args...)
}

func LogErr(err error, format string, args ...interface{}) bool {
	if err != nil {
		args = append(args, err.Error())
		logrus.Infof(format+" %s", args...)
		return false
	}
	return true
}

func Infof(format string, args ...interface{}) {
	logrus.Infof(format, args...)
}

func Warnf(format string, args ...interface{}) {
	logrus.Warnf(format, args...)
}

func Errorf(format string, args ...interface{}) {
	logrus.Errorf(format, args...)
}

func Fatalf(format string, args ...interface{}) {
	logrus.Fatalf(format, args...)
}

func Panicf(format string, args ...interface{}) {
	logrus.Panicf(format, args...)
}

func Debug(args ...interface{}) {
	logrus.Debug(args...)
}

func Info(args ...interface{}) {
	logrus.Info(args...)
}

func Warn(args ...interface{}) {
	logrus.Warn(args...)
}

func Error(args ...interface{}) {
	logrus.Error(args...)
}

func Fatal(args ...interface{}) {
	logrus.Fatal(args...)
}

func Panic(args ...interface{}) {
	logrus.Panic(args...)
}

func SetGinLogger() gin.LoggerConfig {
	var c gin.LoggerConfig
	c.Output = gin.DefaultWriter
	c.Formatter = func(params gin.LogFormatterParams) string {
		userName := GetStr("userId", params.Keys, "")
		var formatStr string
		if params.StatusCode == http.StatusOK {
			formatStr = fmt.Sprintf("%s  %-15s %-16s  %-4s   %s  %d  %s  %s\n",
				params.TimeStamp.Format("2006-01-02 15:04:05"),
				params.ClientIP,
				userName,
				params.Method,
				params.Path,
				params.StatusCode,
				params.Latency,
				params.ErrorMessage,
			)
		} else {
			formatStr = fmt.Sprintf("\x1b[93m%s  %-15s %-16s %-4s   %s  %d  %s  %s\n\x1b[0m",
				params.TimeStamp.Format("2006-01-02 15:04:05"),
				params.ClientIP,
				userName,
				params.Method,
				params.Path,
				params.StatusCode,
				params.Latency,
				params.ErrorMessage,
			)
		}
		// logrus.Infof(" %-15s %-16s %-4s   %s  %d  %s  %s", params.ClientIP, userName,
		// 	params.Method,
		// 	params.Path,
		// 	params.StatusCode,
		// 	params.Latency,
		// 	params.ErrorMessage,
		// )
		return formatStr
	}
	return c

}

func GetStr(key string, obj map[string]interface{}, def string) string {
	if val, flag := obj[key]; flag {
		if sVal, flag2 := val.(string); flag2 {
			return sVal
		}
		if sVal, flag2 := val.(int); flag2 {
			return strconv.Itoa(sVal)
		}
	}
	return def
}
