package main

import (
	"encoding/json"
	"fmt"
	"slices"
	"strings"

	"src.opensuse.org/autogits/common"
	"src.opensuse.org/autogits/common/gitea-generated/models"
)

type PackageRebaseLink struct {
	Pkg          string // fork to track
	SelfRef      bool   // if we reference different branch as upstream, instead of parentRepo
	SourceBranch string // branch to follow, empty for default

	parentRepo *models.Repository
}

func fetchProjectLinksFile(org, prj string) ([]byte, error) {
	return nil, nil
}

func parseProjectLinks(data []byte) ([]*PackageRebaseLink, error) {
	values := make([]*PackageRebaseLink, 0, 100)

	if len(data) == 0 {
		return values, nil
	}

	if err := json.Unmarshal(data, &values); err != nil {
		return nil, err
	}

	slices.SortFunc(values, func(a, b *PackageRebaseLink) int {
		return strings.Compare(a.Pkg, b.Pkg)
	})

	return values, nil
}

func ProcessProjectLinks(gitea common.Gitea, org, prjGit, branch string) ([]*PackageRebaseLink, string, error) {
	data, hash, err := gitea.GetRepositoryFileContent(org, prjGit, branch, common.PrjLinksFile)
	if err != nil {
		return nil, "", err
	}
	links, err := parseProjectLinks(data)
	return links, hash, err
}

func ResolveLinks(org string, links []*PackageRebaseLink, gitea common.GiteaRepoFetcher) {
	for _, link := range links {
		if repo, err := gitea.GetRepository(org, link.Pkg); err == nil {
			if link.SelfRef {
				link.parentRepo = repo
			} else {
				link.parentRepo = repo.Parent
			}

			if len(link.SourceBranch) == 0 {
				link.SourceBranch = repo.DefaultBranch
			}
		}
	}
}

func ListenOrgsForUpdates(links []*PackageRebaseLink) []string {
	orgs := make([]string, 0, len(links))
	for _, link := range links {
		if !slices.Contains(orgs, link.parentRepo.Owner.UserName) {
			orgs = append(orgs, link.parentRepo.Owner.UserName)
		}
	}

	return orgs
}

func (link *PackageRebaseLink) StateUpdater(git common.Git, gitea common.Gitea, pkgSubmoduleDir string) error {
	if link.parentRepo == nil {
		return fmt.Errorf(" *** Can't update link in '%s' -- no parent repository", pkgSubmoduleDir)
	}

	remotes := common.SplitStringNoEmpty(git.GitExecWithOutputOrPanic(pkgSubmoduleDir, "remote"), "\n")
	if !slices.Contains(remotes, "link") {
		git.GitExecWithOutputOrPanic(pkgSubmoduleDir, "remote", "add", "link", link.parentRepo.SSHURL)
	}
	git.GitExecOrPanic(pkgSubmoduleDir, "fetch", "link", link.SourceBranch)
	if err := git.GitExec(pkgSubmoduleDir, "rebase", "link", link.SourceBranch); err != nil {
		git.GitExec(pkgSubmoduleDir, "rebase", "--abort")
		return err
	}

	return nil
}
