package functions

import (
	"fmt"
	"time"

	"github.com/go-git/go-git/v5"
	"github.com/go-git/go-git/v5/plumbing"
)

const FuncSwitchBranch = "switch_branch"

func InitSwitchBranchFunction() Function {
	f := Function{
		Name:        FuncSwitchBranch,
		Description: "Switch the branch. Like git checkout, git switch command.",
		Func:        SwitchBranch,
		Parameters: map[string]any{
			"type": "object",
			"properties": map[string]any{
				"branch": map[string]any{
					"type":        "string",
					"description": "The branch name you want to switch.",
				},
				"create_branch": map[string]any{
					"type":        "boolean",
					"description": "If you create a new branch, set this to true.The name of the branch to be created is generated by the system.",
					"default":     false,
				},
			},
			"required":             []string{"create_branch"},
			"additionalProperties": false,
		},
	}

	register(f)

	return f
}

type SwitchBranchInput struct {
	Branch       string
	CreateBranch bool `json:"create_branch"`
}

func makeBranchName() string {
	return fmt.Sprintf("%s%d", "agent-", time.Now().UnixNano())
}

func SwitchBranch(input SwitchBranchInput) (string, error) {
	repo, err := git.PlainOpen(".")
	if err != nil {
		return "", fmt.Errorf("failed to open repository: %w", err)
	}

	wt, err := repo.Worktree()
	if err != nil {
		return "", fmt.Errorf("failed to get worktree: %w", err)
	}

	href, err := repo.Head()
	if err != nil {
		return "", fmt.Errorf("failed to get head reference: %w", err)
	}

	branchName := input.Branch
	if input.CreateBranch {
		branchName = makeBranchName()
		ref := plumbing.NewHashReference(plumbing.NewBranchReferenceName(branchName), href.Hash())
		if err := repo.Storer.SetReference(ref); err != nil {
			return "", fmt.Errorf("failed to create branch reference: %w", err)
		}
	}

	if err := wt.Checkout(&git.CheckoutOptions{
		Branch: plumbing.NewBranchReferenceName(branchName),
		Keep:   true,
	}); err != nil {
		return "", fmt.Errorf("failed to checkout branch %s: %w", branchName, err)
	}

	return fmt.Sprintf("success switch to %s", branchName), nil
}
