package eduvpnapi

import (
	"context"
	"net/http"
	"sync"
	"time"

	"codeberg.org/eduVPN/eduvpn-common/internal/eduvpnapi/endpoints"
)

// EndpointCache is a struct that caches well-known API endpoints
type EndpointCache struct {
	lastUpdate map[string]time.Time
	lastEP     map[string]*endpoints.Endpoints
	mu         sync.Mutex
}

// Get returns a cached or fresh endpoint cache copy
func (ec *EndpointCache) Get(ctx context.Context, wk string, transport http.RoundTripper) (*endpoints.Endpoints, error) {
	ec.mu.Lock()
	defer ec.mu.Unlock()

	// get the last update time
	lu := time.Time{}
	if v, ok := ec.lastUpdate[wk]; ok {
		lu = v
	}

	// if not 10 minutes have passed, return cached copy
	if !lu.IsZero() && !time.Now().After(lu.Add(10*time.Minute)) {
		v, ok := ec.lastEP[wk]
		if ok {
			return v, nil
		}
	}

	// get fresh API endpoints
	ep, err := getEndpoints(ctx, wk, transport)
	if err != nil {
		return nil, err
	}

	// update endpoints
	ec.lastUpdate[wk] = time.Now()
	ec.lastEP[wk] = ep

	return ep, nil
}

var (
	epCache     *EndpointCache
	epCacheOnce sync.Once
)

// GetEndpointCache returns the global singleton endpoint cache
// or creates one if it does not exist
func GetEndpointCache() *EndpointCache {
	epCacheOnce.Do(func() {
		epCache = &EndpointCache{
			lastUpdate: make(map[string]time.Time),
			lastEP:     make(map[string]*endpoints.Endpoints),
		}
	})

	return epCache
}
