package gl

import (
	"context"
	"github.com/go-kratos/kratos/v2/log"
	"go.opentelemetry.io/otel"
	"go.opentelemetry.io/otel/attribute"
	semconv "go.opentelemetry.io/otel/semconv/v1.4.0"
	"go.opentelemetry.io/otel/trace"
	"gorm.io/gorm/logger"
	"strings"
	"time"
)

type Logger struct {
	*log.Helper
}

func (l *Logger) LogMode(level logger.LogLevel) logger.Interface {
	return l
}

func (l *Logger) Info(ctx context.Context, s string, i ...interface{}) {
	l.WithContext(ctx).Info(s, i)
}

func (l *Logger) Warn(ctx context.Context, s string, i ...interface{}) {
	l.WithContext(ctx).Warn(s, i)
}

func (l *Logger) Error(ctx context.Context, s string, i ...interface{}) {
	l.WithContext(ctx).Error(s, i)
}

func (l *Logger) Trace(ctx context.Context, begin time.Time, fc func() (sql string, rowsAffected int64), err error) {
	sql, rowsAffected := fc()
	MysqlTracer(ctx, begin, sql, int(rowsAffected))
	l.WithContext(ctx).Infof("[%s]db trace sql:%s, rowsAffected:%d, err:%v", begin, sql, rowsAffected, err)
}

func MysqlTracer(ctx context.Context, begin time.Time, sql string, rowsAffected int) {
	tracer := otel.Tracer("Mysql")
	kind := trace.SpanKindInternal
	strs := strings.Split(sql, " ")
	ctx, span := tracer.Start(ctx,
		strs[0],
		trace.WithSpanKind(kind),
		trace.WithTimestamp(begin),
	)
	var attrs []attribute.KeyValue
	attrs = append(attrs, semconv.DBSystemMySQL)
	attrs = append(attrs, semconv.DBStatementKey.String(sql))
	attrs = append(attrs, attribute.Int("db.rows_affected", rowsAffected))
	span.SetAttributes(attrs...)
	span.End(trace.WithTimestamp(time.Now()))
}