package server

import (
	"net/http"
	"strings"

	"codeberg.org/codeberg/pages/html"
	"codeberg.org/codeberg/pages/server/cache"
	"codeberg.org/codeberg/pages/server/context"
	"codeberg.org/codeberg/pages/server/gitea"
	"codeberg.org/codeberg/pages/server/upstream"
	"github.com/rs/zerolog"
)

// tryUpstream forwards the target request to the Gitea API, and shows an error page on failure.
func tryUpstream(ctx *context.Context, giteaClient *gitea.Client,
	mainDomainSuffix, trimmedHost string,

	targetOptions *upstream.Options,
	targetOwner, targetRepo, targetBranch, targetPath string,

	canonicalDomainCache cache.SetGetKey,
) {
	// check if a canonical domain exists on a request on MainDomain
	if strings.HasSuffix(trimmedHost, mainDomainSuffix) {
		canonicalDomain, _ := upstream.CheckCanonicalDomain(giteaClient, targetOwner, targetRepo, targetBranch, "", string(mainDomainSuffix), canonicalDomainCache)
		if !strings.HasSuffix(strings.SplitN(canonicalDomain, "/", 2)[0], string(mainDomainSuffix)) {
			canonicalPath := ctx.Req.RequestURI
			if targetRepo != "pages" {
				path := strings.SplitN(canonicalPath, "/", 3)
				if len(path) >= 3 {
					canonicalPath = "/" + path[2]
				}
			}
			ctx.Redirect("https://"+canonicalDomain+canonicalPath, http.StatusTemporaryRedirect)
			return
		}
	}

	targetOptions.TargetOwner = targetOwner
	targetOptions.TargetRepo = targetRepo
	targetOptions.TargetBranch = targetBranch
	targetOptions.TargetPath = targetPath
	targetOptions.Host = string(trimmedHost)

	// Try to request the file from the Gitea API
	if !targetOptions.Upstream(ctx, giteaClient) {
		html.ReturnErrorPage(ctx, "", ctx.StatusCode)
	}
}

// tryBranch checks if a branch exists and populates the target variables. If canonicalLink is non-empty,
// it will also disallow search indexing and add a Link header to the canonical URL.
func tryBranch(log zerolog.Logger, ctx *context.Context, giteaClient *gitea.Client,
	repoOwner, repoName, branch, path string, canonicalLink bool,
) (*gitea.BranchTimestamp, bool) {
	if repoName == "" {
		log.Debug().Msg("tryBranch: repo is empty")
		return nil, false
	}

	// Replace "~" to "/" so we can access branch that contains slash character
	// Branch name cannot contain "~" so doing this is okay
	branch = strings.ReplaceAll(branch, "~", "/")

	// Check if the branch exists, otherwise treat it as a file path
	branchTimestampResult := upstream.GetBranchTimestamp(giteaClient, repoOwner, repoName, branch)
	if branchTimestampResult == nil {
		log.Debug().Msg("tryBranch: branch doesn't exist")
		return nil, false
	}

	if canonicalLink {
		// Hide from search machines & add canonical link
		ctx.RespWriter.Header().Set("X-Robots-Tag", "noarchive, noindex")
		ctx.RespWriter.Header().Set("Link",
			giteaClient.ContentWebLink(repoOwner, repoName, branchTimestampResult.Branch, path)+
				"; rel=\"canonical\"")
	}

	log.Debug().Msg("tryBranch: true")
	return branchTimestampResult, true
}