package main

import (
	"code.gitea.io/sdk/gitea"
	"fmt"
	"github.com/gofiber/fiber/v2"
	"github.com/gofiber/fiber/v2/middleware/recover"
	"github.com/kpango/glg"
)

type Channel int

const (
	Stable Channel = iota
	Prerelease
)

type Attachement struct {
	User     string
	Repo     string
	Tag      string
	Filename string
	Channel  Channel
}

const giteaURL = "https://git.entr0py.de"

func getAttachementURL(attachement Attachement) (string, error) {
	client, err := gitea.NewClient(giteaURL)
	if err != nil {
		return "", fmt.Errorf("Failed to create gitea client: %v")
	}
	var release *gitea.Release
	if attachement.Tag != "" {
		release, _, err = client.GetReleaseByTag(attachement.User, attachement.Repo, attachement.Tag)
		if err != nil {
			return "", fmt.Errorf("Failed to get release by tag: %v")
		}
	} else {
		isPrerelease := false
		if attachement.Channel == Prerelease {
			isPrerelease = true
		}
		releases, _, err := client.ListReleases(attachement.User, attachement.Repo, gitea.ListReleasesOptions{IsPreRelease: &isPrerelease})
		if err != nil {
			return "", fmt.Errorf("Failed to get releases: %v")
		}
		if len(releases) == 0 {
			return "", fmt.Errorf("no release found")
		}
		release = releases[0]
	}
	for _, a := range release.Attachments {
		if a.Name == attachement.Filename {
			return a.DownloadURL, nil
		}
	}
	return "", fmt.Errorf("no matching attachement found")
}

func main() {

	app := fiber.New(fiber.Config{
		GETOnly:      true,
		ServerHeader: "Fiber",
		AppName:      "Test App v1.0.1",
	})
	app.Use(recover.New())

	app.Get("/:user/:repo/releases/download/latest/:name", func(c *fiber.Ctx) error {
		glg.Debugf("%+v", map[string]string{"user": c.Params("user"), "repo": c.Params("repo"), "name": c.Params("name")})
		attachement := Attachement{
			User:     c.Params("user"),
			Repo:     c.Params("repo"),
			Filename: c.Params("name"),
			Channel:  Stable,
		}
		url, err := getAttachementURL(attachement)
		if err != nil {
			glg.Debug(err)
			c.SendString(err.Error())
			c.SendStatus(404)
			return nil
		}
		c.Redirect(url, 307)
		return nil
	})

	app.Get("/:user/:repo/releases/download/latest\\::channel/:name", func(c *fiber.Ctx) error {
		glg.Debugf("%+v", map[string]string{"user": c.Params("user"), "repo": c.Params("repo"), "name": c.Params("name"), "channel": c.Params("channel")})
		channel := Stable
		if c.Params("channel") == "prerelease" {
			channel = Prerelease
		}
		attachement := Attachement{
			User:     c.Params("user"),
			Repo:     c.Params("repo"),
			Filename: c.Params("name"),
			Channel:  channel,
		}
		url, err := getAttachementURL(attachement)
		if err != nil {
			glg.Debug(err)
			c.SendString(err.Error())
			c.SendStatus(404)
			return nil
		}
		c.Redirect(url, 307)
		return nil
	})

	app.Get("/:user/:repo/releases/download/tag\\::tag/:name", func(c *fiber.Ctx) error {
		glg.Debugf("%+v", map[string]string{"user": c.Params("user"), "repo": c.Params("repo"), "name": c.Params("name"), "tag": c.Params("tag")})
		attachement := Attachement{
			User:     c.Params("user"),
			Repo:     c.Params("repo"),
			Filename: c.Params("name"),
			Tag:      c.Params("tag"),
		}
		url, err := getAttachementURL(attachement)
		if err != nil {
			glg.Debug(err)
			c.SendString(err.Error())
			c.SendStatus(404)
			return nil
		}
		c.Redirect(url, 307)
		return nil
	})

	app.Listen(":8080")
}