package github

import (
	"context"
	"fmt"
	"time"

	"github.com/databricks/cli/cmd/labs/localcache"
	"github.com/databricks/cli/libs/log"
)

const cacheTTL = 1 * time.Hour

// NewReleaseCache creates a release cache for a repository in the GitHub org.
// Caller has to provide different cache directories for different repositories.
func NewReleaseCache(org, repo, cacheDir string) *ReleaseCache {
	pattern := fmt.Sprintf("%s-%s-releases", org, repo)
	return &ReleaseCache{
		cache: localcache.NewLocalCache[Versions](cacheDir, pattern, cacheTTL),
		Org:   org,
		Repo:  repo,
	}
}

type ReleaseCache struct {
	cache localcache.LocalCache[Versions]
	Org   string
	Repo  string
}

func (r *ReleaseCache) Load(ctx context.Context) (Versions, error) {
	return r.cache.Load(ctx, func() (Versions, error) {
		return getVersions(ctx, r.Org, r.Repo)
	})
}

// getVersions is considered to be a private API, as we want the usage go through a cache
func getVersions(ctx context.Context, org, repo string) (Versions, error) {
	var releases Versions
	log.Debugf(ctx, "Fetching latest releases for %s/%s from GitHub API", org, repo)
	url := fmt.Sprintf("%s/repos/%s/%s/releases", gitHubAPI, org, repo)
	err := httpGetAndUnmarshal(ctx, url, &releases)
	return releases, err
}

type ghAsset struct {
	Name               string `json:"name"`
	ContentType        string `json:"content_type"`
	Size               int    `json:"size"`
	BrowserDownloadURL string `json:"browser_download_url"`
}

type Release struct {
	Version     string    `json:"tag_name"`
	CreatedAt   time.Time `json:"created_at"`
	PublishedAt time.Time `json:"published_at"`
	ZipballURL  string    `json:"zipball_url"`
	Assets      []ghAsset `json:"assets"`
}

type Versions []Release