package appcontext

import (
	"context"
	"github.com/google/uuid"
	"github.com/sirupsen/logrus"
)

type logCtxKeyType struct{}

var logCtxKey = logCtxKeyType(struct{}{})

type Logger struct {
	*logrus.Logger
}

var log *Logger

type ContextInfo struct {
	CorrelationID  string
	UserID         uuid.UUID
	OrganizationID uuid.UUID
	OutletID       uuid.UUID
	AppVersion     string
	AppID          string
	AppType        string
	Platform       string
	DeviceOS       string
	UserLocale     string
	UserRole       string
}

type ctxKeyType struct{}

var ctxKey = ctxKeyType(struct{}{})

func NewAppContext(ctx context.Context, info *ContextInfo) context.Context {
	ctx = NewContext(ctx, map[string]interface{}{
		"correlation_id": info.CorrelationID,
		"user_id":        info.UserID,
		"app_version":    info.AppVersion,
		"app_id":         info.AppID,
		"app_type":       info.AppType,
		"platform":       info.Platform,
		"device_os":      info.DeviceOS,
		"user_locale":    info.UserLocale,
	})
	return context.WithValue(ctx, ctxKey, info)
}

func NewContext(ctx context.Context, baseFields map[string]interface{}) context.Context {
	entry, ok := ctx.Value(logCtxKey).(*logrus.Entry)
	if !ok {
		entry = log.WithFields(map[string]interface{}{})
	}

	return context.WithValue(ctx, logCtxKey, entry.WithFields(baseFields))
}

func FromGinContext(ctx context.Context) *ContextInfo {
	return &ContextInfo{
		CorrelationID:  value(ctx, CorrelationIDKey),
		UserID:         uuidValue(ctx, UserIDKey),
		OutletID:       uuidValue(ctx, OutletIDKey),
		OrganizationID: uuidValue(ctx, OrganizationIDKey),
		AppVersion:     value(ctx, AppVersionKey),
		AppID:          value(ctx, AppIDKey),
		AppType:        value(ctx, AppTypeKey),
		Platform:       value(ctx, PlatformKey),
		DeviceOS:       value(ctx, DeviceOSKey),
		UserLocale:     value(ctx, UserLocaleKey),
		UserRole:       value(ctx, UserRoleKey),
	}
}

func FromContext(ctx context.Context) *ContextInfo {
	if info, ok := ctx.Value(ctxKey).(*ContextInfo); ok {
		return info
	}
	return nil
}
