package auditlog

import (
	"context"
	"errors"
	"net/http"
	"strings"

	usersvc "github.com/tidbcloud/account/internel/svc/user"

	"github.com/pingcap/errcode"
	audit_event "github.com/tidbcloud/pkgv2/log"
	"github.com/tidbcloud/tiinf/monitor/tilog"
	"go.uber.org/zap"
	"google.golang.org/grpc/metadata"
)

func SetupAuditLogger() {
	audit_event.AUDIT_LOG_DEFAULT_FILE_PATH = "/var/log/central/audit.log"
	audit_event.InitAuditLogger(
		audit_event.AUDIT_LOG_DEFAULT_FILE_PATH,
		audit_event.AUDIT_LOG_DEFAULT_MAX_FILE_SIZE,
		audit_event.AUDIT_LOG_DEFAULT_MAX_BACKUPS,
		audit_event.AUDIT_LOG_DEFAULT_MAX_DAYS,
	)
}

func AuditLog(ctx context.Context, err error, eventType audit_event.AuditEventType, fields ...zap.Field) {
	// if !config.Global().ServerConfig.AuthLogSwitch {
	// 	return
	// }
	tilog.Info(ctx, "start to record audit log", zap.String("eventType", string(eventType)))
	audit := audit_event.NewAuditSession(eventType)
	if clientIP, err := GetClientIP(ctx); err == nil {
		audit.SetClientIP(clientIP)
	}
	if user, err := usersvc.GetUserFromContext(ctx); err == nil {
		audit.SetUserID(uint64(user.ID))
	}
	audit.IsSuccess(err == nil)
	audit.AddFields(fields...)
	audit.Submit()
}

func GetClientIP(ctx context.Context) (string, error) {
	md, ok := metadata.FromIncomingContext(ctx)
	if !ok {
		return "", errcode.NewInternalErr(errors.New("failed to invoke FromIncomingContext"))
	}

	rips := md.Get("X-Forwarded-For")
	if len(rips) == 0 || rips[0] == "" {
		return "", errcode.NewInternalErr(errors.New("remote real addr is empty"))
	}

	// Remove proxy IPs from Forwarded-For header
	// https://en.wikipedia.org/wiki/X-Forwarded-For
	rip := strings.Split(rips[0], ",")[0]

	return rip, nil
}

// copy from GetClientIP
func GetClientIpFromReq(req *http.Request) string {
	if req == nil {
		return ""
	}
	rips := req.Header["X-Forwarded-For"]
	if len(rips) == 0 || rips[0] == "" {
		return ""
	}
	return strings.Split(rips[0], ",")[0]
}
