package gitstore

import (
	"context"
	"fmt"
	"os/exec"
	"strings"

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

const (
	// defaultCommitName is the committer name used for system-generated commits.
	defaultCommitName = "gh-server"
	// defaultCommitEmail is the committer email used for system-generated commits.
	defaultCommitEmail = "gh-server@localhost"
)

// UpdatePRBranchOptions defines options for the UpdatePRBranch operation.
type UpdatePRBranchOptions struct {
	FullName     string
	BaseBranch   string
	HeadBranch   string
	Committer    string
	Email        string
	UpdateMethod string
}

// CanMerge checks whether headBranch can be cleanly merged into baseBranch
// using git merge-tree (no worktree needed). Returns "MERGEABLE", "CONFLICTING", or "UNKNOWN".
func (s *Store) CanMerge(ctx context.Context, fullName, baseBranch, headBranch string) string {
	repoDir, err := s.repoPath(ctx, fullName)
	if err != nil {
		return "UNKNOWN"
	}
	cmd := exec.CommandContext(ctx, "git", "-C", repoDir, "merge-tree",
		"--write-tree", "--no-messages",
		plumbing.NewBranchReferenceName(baseBranch).String(),
		plumbing.NewBranchReferenceName(headBranch).String())
	if err := cmd.Run(); err != nil {
		return "CONFLICTING"
	}
	return "MERGEABLE"
}

// IsEmpty reports whether the repository has no commits.
func (s *Store) IsEmpty(ctx context.Context, fullName string) bool {
	repoDir, err := s.repoPath(ctx, fullName)
	if err != nil {
		return true
	}
	cmd := exec.CommandContext(ctx, "git", "-C", repoDir, "cat-file", "-t", "HEAD")
	return cmd.Run() != nil
}

// DiskUsageKB returns the approximate size of a repository in kilobytes.
func (s *Store) DiskUsageKB(ctx context.Context, fullName string) int {
	repoDir, err := s.repoPath(ctx, fullName)
	if err != nil {
		return 0
	}
	cmd := exec.CommandContext(ctx, "du", "-sk", repoDir)
	out, err := cmd.Output()
	if err != nil {
		return 0
	}
	var kb int
	fmt.Sscanf(strings.TrimSpace(string(out)), "%d", &kb)
	return kb
}
