package middleware

import (
	"context"
	"fmt"
	"time"

	"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/creds/accessbox"
)

// keyWrapper is wrapper for context keys.
type keyWrapper string

// authHeaders is a wrapper for authentication headers of a request.
var authHeadersKey = keyWrapper("__context_auth_headers_key")

// boxData is an ID used to store accessbox.Box in a context.
var boxDataKey = keyWrapper("__context_box_key")

// clientTime is an ID used to store client time.Time in a context.
var clientTimeKey = keyWrapper("__context_client_time")

// GetBoxData  extracts accessbox.Box from context.
func GetBoxData(ctx context.Context) (*accessbox.Box, error) {
	var box *accessbox.Box
	data, ok := ctx.Value(boxDataKey).(*accessbox.Box)
	if !ok || data == nil {
		return nil, fmt.Errorf("couldn't get box data from context")
	}

	box = data
	if box.Gate == nil {
		box.Gate = &accessbox.GateData{}
	}
	return box, nil
}

// GetAuthHeaders extracts auth.AuthHeader from context.
func GetAuthHeaders(ctx context.Context) (*AuthHeader, error) {
	authHeaders, ok := ctx.Value(authHeadersKey).(*AuthHeader)
	if !ok {
		return nil, fmt.Errorf("couldn't get auth headers from context")
	}

	return authHeaders, nil
}

// GetClientTime extracts time.Time from context.
func GetClientTime(ctx context.Context) (time.Time, error) {
	clientTime, ok := ctx.Value(clientTimeKey).(time.Time)
	if !ok {
		return time.Time{}, fmt.Errorf("couldn't get client time from context")
	}

	return clientTime, nil
}

// SetBoxData sets accessbox.Box in the context.
func SetBoxData(ctx context.Context, box *accessbox.Box) context.Context {
	return context.WithValue(ctx, boxDataKey, box)
}

// SetAuthHeaders sets auth.AuthHeader in the context.
func SetAuthHeaders(ctx context.Context, header *AuthHeader) context.Context {
	return context.WithValue(ctx, authHeadersKey, header)
}

// SetClientTime sets time.Time in the context.
func SetClientTime(ctx context.Context, newTime time.Time) context.Context {
	return context.WithValue(ctx, clientTimeKey, newTime)
}