package revenuecat

import (
	"fmt"
	"log"
	"strings"
	"sync"
	"time"

	"github.com/mhemmings/revenuecat"
)

type UIDData struct {
	lastUpdateTime int64
	entitled       bool
}

// the revenuecat client
var revenueCatClient *revenuecat.Client

// the revenuecat entitlement cache
// this stores the entitlement status locally to avoid frequent revenuecat API requests
// the key is the "${uid}-${entitlementName}" and the value is the entitlement bool with a date
var entitlementCache map[string]UIDData = make(map[string]UIDData)
var entitlementCacheLock sync.Mutex

// Init initializes all firebase assets
func Init() {
	log.Print("Initializing RevenueCat...")
	createClient()
}

// Entitled returns if the uid associated with the token is entitled to pro
func HasEntitlement(uid string, entitlement string) bool {
	entitled, err := getEntitled(uid, entitlement)
	if err != nil {
		log.Printf("Error getting entitlement: %v\n", err)
		// assume its pro
		return true
	}
	return entitled
}

// clears the cache for a specific uid
func ClearCache(uid string) {
	if uid == "" {
		return
	}

	entitlementCacheLock.Lock()
	for key := range entitlementCache {
		if strings.HasPrefix(key, uid) {
			delete(entitlementCache, key)
		}
	}
	entitlementCacheLock.Unlock()
}

// creates a new revenuecat client
func createClient() {
	revenueCatClient = revenuecat.New("sk_RZaxptlptFXDSJrlIINgkzExEwhkm")
}

func getEntitled(uid string, entitlement string) (bool, error) {

	// pull from cache is in cache and still valid
	entitlementCacheLock.Lock()
	var key = fmt.Sprintf("%s-%s", uid, entitlement)
	val, ok := entitlementCache[key]
	entitlementCacheLock.Unlock()
	if ok {
		now := time.Now().UnixMilli()
		if (now - val.lastUpdateTime) < 60*60*1000 {
			return val.entitled, nil
		}
	}

	// otherwise pull from API and put in cache
	sub, err := revenueCatClient.GetSubscriber(uid)
	if err != nil {
		log.Printf("Error pulling subscriber data: %v %v\n", err, uid)
		// create a new client in case the issue is related to the http client being in a bad state
		createClient()
		return false, err
	}
	entitled := sub.IsEntitledTo(entitlement)
	entitlementCacheLock.Lock()
	entitlementCache[key] = UIDData{
		lastUpdateTime: time.Now().UnixMilli(),
		entitled:       entitled,
	}
	entitlementCacheLock.Unlock()

	return entitled, nil
}
