// poprepo is a package for populating a git repo with commits that associate
// a git commit with a buildid, a monotonically increasing number maintained
// by a external build system. This is needed because Perf only knows how
// to associate measurement values with git commits.
package poprepo

import (
	"bytes"
	"context"
	"fmt"
	"net/url"
	"os"
	"path/filepath"
	"strconv"
	"strings"

	"go.skia.org/infra/go/exec"
	"go.skia.org/infra/go/git"
	"go.skia.org/infra/go/skerr"
	"go.skia.org/infra/go/sklog"
)

const (
	BUILDID_FILENAME = "BUILDID"
)

// PopRepoI is the interface that PopRepo supports.
//
// It supports adding and reading BuildIDs from a git repo.
type PopRepoI interface {
	// GetLast returns the last committed buildid, its timestamp, and git hash.
	GetLast(ctx context.Context) (int64, int64, string, error)

	// Add a new buildid to the repo.
	Add(ctx context.Context, buildid, ts int64) error

	// LookupBuildID looks up a buildid and branch from the git hash.
	LookupBuildID(ctx context.Context, hash string) (int64, error)
}

// PopRepo implements PopRepoI.
type PopRepo struct {
	checkout  *git.Checkout
	workdir   string
	local     bool
	subdomain string
}

// NewPopRepo returns a *PopRepo that writes and reads BuildIds into the
// 'checkout'.
//
// If not 'local' then the HOME environment variable is set for running on the
// server.
func NewPopRepo(checkout *git.Checkout, local bool, subdomain string) *PopRepo {
	return &PopRepo{
		checkout:  checkout,
		workdir:   checkout.Dir(),
		local:     local,
		subdomain: subdomain,
	}
}

// GetLast returns the last buildid, the timestamp of when that buildid was
// added, and the git hash.
//
// The timestamp is seconds since the Unix epoch.
func (p *PopRepo) GetLast(ctx context.Context) (int64, int64, string, error) {
	fullpath := filepath.Join(p.checkout.Dir(), BUILDID_FILENAME)
	b, err := os.ReadFile(fullpath)
	if err != nil {
		return 0, 0, "", fmt.Errorf("Unable to read file %q: %s", fullpath, err)
	}
	s := strings.TrimSpace(string(b))
	parts := strings.Split(s, " ")
	if len(parts) != 2 {
		return 0, 0, "", fmt.Errorf("Unable to find just buildid and timestamp in: %q", s)
	}
	ts, err := strconv.ParseInt(parts[1], 10, 64)
	if err != nil {
		return 0, 0, "", fmt.Errorf("Timestamp is invalid in %q: %s", s, err)
	}
	buildid, err := strconv.ParseInt(parts[0], 10, 64)
	if err != nil {
		return 0, 0, "", fmt.Errorf("BuildID is invalid in %q: %s", s, err)
	}
	hash, err := p.checkout.RevParse(ctx, "HEAD")
	if err != nil {
		return 0, 0, "", fmt.Errorf("Unable to retrieve git hash: %s", err)
	}
	return buildid, ts, hash, nil
}

// See PopRepoI.
func (p *PopRepo) LookupBuildID(ctx context.Context, hash string) (int64, error) {
	commit, err := p.checkout.Details(ctx, hash)
	if err != nil {
		return -1, fmt.Errorf("Failed looking up buildid: %s", err)
	}
	u, err := url.Parse(commit.Subject)
	if err != nil {
		return -1, fmt.Errorf("Commit subject was not a valid URL: %s", err)
	}
	id, err := strconv.ParseInt(filepath.Base(u.Path), 10, 64)
	return id, err
}

// Add a new buildid and its assocatied Unix timestamp to the repo.
func (p *PopRepo) Add(ctx context.Context, buildid int64, ts int64) error {
	rollback := false
	defer func() {
		if !rollback {
			return
		}
		if err := p.checkout.UpdateBranch(ctx, git.MainBranch); err != nil {
			sklog.Errorf("While rolling back failed Add(): Unable to update the checkout at %q: %s", p.checkout.Dir(), err)
		}
	}()

	// Need to set GIT_COMMITTER_DATE with commit call.
	gitExec, err := git.Executable(ctx)
	if err != nil {
		return skerr.Wrap(err)
	}
	output := bytes.Buffer{}
	cmd := exec.Command{
		Name: gitExec,
		// If this commit message changes, also change Cache.parseLog.
		Args:           []string{"commit", "-m", fmt.Sprintf("https://android-build.googleplex.com/builds/jump-to-build/%d", buildid), fmt.Sprintf("--date=%d", ts)},
		Env:            []string{fmt.Sprintf("GIT_COMMITTER_DATE=%d", ts)},
		Dir:            p.checkout.Dir(),
		InheritEnv:     true,
		CombinedOutput: &output,
	}
	if !p.local {
		// Should be set by server.
		cmd.Env = append(cmd.Env, fmt.Sprintf("HOME=/home/skia"))
	}

	// Also needs to confirm that the buildids are ascending, which means they should be ints.
	lastBuildID, _, _, err := p.GetLast(ctx)
	if err != nil {
		return fmt.Errorf("Couldn't get last buildid: %s", err)
	}
	if buildid <= lastBuildID {
		return fmt.Errorf("Error: buildid=%d <= lastBuildID=%d, buildid added in wrong order.", buildid, lastBuildID)
	}
	if err := os.WriteFile(filepath.Join(p.checkout.Dir(), BUILDID_FILENAME), []byte(fmt.Sprintf("%d %d", buildid, ts)), 0644); err != nil {
		rollback = true
		return fmt.Errorf("Failed to write updated buildid: %s", err)
	}
	if msg, err := p.checkout.Git(ctx, "add", BUILDID_FILENAME); err != nil {
		rollback = true
		return fmt.Errorf("Failed to add updated file %q: %s", msg, err)
	}
	if err := exec.Run(ctx, &cmd); err != nil {
		rollback = true
		return fmt.Errorf("Failed to commit updated file %q: %s", output.String(), err)
	}
	fmt.Printf("git commit: %q", output.String())
	if msg, err := p.checkout.Git(ctx, "push", git.DefaultRemote, git.MainBranch); err != nil {
		rollback = true
		return fmt.Errorf("Failed to push updated checkout %q: %s", msg, err)
	}

	return nil
}

// Verify that PopRepo implements PopRepoI.
var _ PopRepoI = (*PopRepo)(nil)
