package tigorm

import (
	"context"
	"fmt"
	"time"

	"github.com/tidbcloud/tiinf/monitor/tilog"
	"go.uber.org/zap"
	"gorm.io/gorm"
	"gorm.io/gorm/logger"
)

// loggerAdapter implements the gorm logger.Interface.
type loggerAdapter struct {
	enableTrace bool
	level       logger.LogLevel
}

func NewLoggerAdapter(enableTrace bool, level logger.LogLevel) *loggerAdapter {
	return &loggerAdapter{enableTrace, level}
}

// LogMode implements the logger.Interface interface
func (l *loggerAdapter) LogMode(level logger.LogLevel) logger.Interface {
	l.level = level
	return l
}

// Info implements the logger.Interface interface
func (l *loggerAdapter) Info(ctx context.Context, format string, args ...interface{}) {
	if l.level < logger.Info {
		return
	}
	tilog.Info(ctx, fmt.Sprintf(format, args...))
}

// Warn implements the logger.Interface interface
func (l *loggerAdapter) Warn(ctx context.Context, format string, args ...interface{}) {
	if l.level < logger.Warn {
		return
	}
	tilog.Warn(ctx, fmt.Sprintf(format, args...))
}

// Error implements the logger.Interface interface
func (l *loggerAdapter) Error(ctx context.Context, format string, args ...interface{}) {
	if l.level < logger.Error {
		return
	}
	tilog.Error(ctx, fmt.Sprintf(format, args...))
}

// Trace implements the logger.Interface interface
func (l *loggerAdapter) Trace(ctx context.Context, _ time.Time, fc func() (string, int64), err error) {
	if l.enableTrace || err != nil {
		sql, _ := fc()
		if err != nil {
			if err == gorm.ErrRecordNotFound {
				tilog.Info(ctx, "GORM Trace", zap.String("SQL", sql))
			} else {
				tilog.Error(ctx, "GORM Trace", zap.String("SQL", sql), zap.Error(err))
			}
		} else {
			tilog.Debug(ctx, "GORM Trace", zap.String("SQL", sql), zap.Error(err))
		}
	}
}
