package codereview

import (
	"bytes"
	"context"
	"fmt"
	"log/slog"
	"os"
	"os/exec"
	"path/filepath"
	"slices"
	"strings"

	"sketch.dev/claudetool"
)

// A CodeReviewer manages quality checks.
type CodeReviewer struct {
	repoRoot        string
	initialCommit   string
	initialStatus   []fileStatus // git status of files at initial commit, absolute paths
	reviewed        []string     // history of all commits which have been reviewed
	initialWorktree string       // git worktree at initial commit, absolute path
	llmReview       bool         // enables a subagent LLM review
}

const (
	NoLLMReview = false
	DoLLMReview = true
)

func NewCodeReviewer(ctx context.Context, repoRoot, initialCommit string, llmReview bool) (*CodeReviewer, error) {
	r := &CodeReviewer{
		repoRoot:      repoRoot,
		initialCommit: initialCommit,
		llmReview:     llmReview,
	}
	if r.repoRoot == "" {
		return nil, fmt.Errorf("NewCodeReviewer: repoRoot must be non-empty")
	}
	if r.initialCommit == "" {
		return nil, fmt.Errorf("NewCodeReviewer: initialCommit must be non-empty")
	}
	// Confirm that root is in fact the git repo root.
	root, err := claudetool.FindRepoRoot(r.repoRoot)
	if err != nil {
		return nil, err
	}
	if root != r.repoRoot {
		return nil, fmt.Errorf("NewCodeReviewer: repoRoot=%q but git repo root is %q", r.repoRoot, root)
	}

	// Get an initial list of dirty and untracked files.
	// We'll filter them out later when deciding whether the worktree is clean.
	status, err := r.repoStatus(ctx)
	if err != nil {
		return nil, err
	}
	r.initialStatus = status
	return r, nil
}

// autoformat formats all files changed in HEAD.
// It returns a list of all files that were formatted.
// It is best-effort only.
func (r *CodeReviewer) autoformat(ctx context.Context) []string {
	// Refuse to format if initial commit is not an ancestor of HEAD
	err := r.requireHEADDescendantOfInitialCommit(ctx)
	if err != nil {
		slog.WarnContext(ctx, "CodeReviewer.Autoformat refusing to format", "err", err)
		return nil
	}

	head, err := r.CurrentCommit(ctx)
	if err != nil {
		slog.WarnContext(ctx, "CodeReviewer.Autoformat unable to get current commit", "err", err)
		return nil
	}
	parent, err := r.ResolveCommit(ctx, "HEAD^1")
	if err != nil {
		slog.WarnContext(ctx, "CodeReviewer.Autoformat unable to get parent commit", "err", err)
		return nil
	}
	// Retrieve a list of all files changed
	// TODO: instead of one git diff --name-only and then N --name-status, do one --name-status.
	changedFiles, err := r.changedFiles(ctx, r.initialCommit, head)
	if err != nil {
		slog.WarnContext(ctx, "CodeReviewer.Autoformat unable to get changed files", "err", err)
		return nil
	}

	// General strategy: For all changed files,
	// run the strictest formatter that passes on the original version.
	// TODO: add non-Go formatters?
	// TODO: at a minimum, for common file types, ensure trailing newlines and maybe trim trailing whitespace per line?
	var fmtFiles []string
	for _, file := range changedFiles {
		if !strings.HasSuffix(file, ".go") {
			continue
		}
		fileStatus, err := r.gitFileStatus(ctx, file)
		if err != nil {
			slog.WarnContext(ctx, "CodeReviewer.Autoformat unable to get file status", "file", file, "err", err)
			continue
		}
		if fileStatus == "D" { // deleted, nothing to format
			continue
		}
		code, err := r.getFileContentAtCommit(ctx, file, head)
		if err != nil {
			slog.WarnContext(ctx, "CodeReviewer.Autoformat unable to get file content at head", "file", file, "err", err)
			continue
		}
		if claudetool.IsAutogeneratedGoFile(code) { // leave autogenerated files alone
			continue
		}
		onDisk, err := os.ReadFile(file)
		if err != nil {
			slog.WarnContext(ctx, "CodeReviewer.Autoformat unable to read file", "file", file, "err", err)
			continue
		}
		if !bytes.Equal(code, onDisk) { // file has been modified since HEAD
			slog.WarnContext(ctx, "CodeReviewer.Autoformat file modified since HEAD", "file", file, "err", err)
			continue
		}
		var formatterToUse string
		if fileStatus == "A" {
			formatterToUse = "gofumpt" // newly added, so we can format how we please: use gofumpt
		} else {
			prev, err := r.getFileContentAtCommit(ctx, file, parent)
			if err != nil {
				slog.WarnContext(ctx, "CodeReviewer.Autoformat unable to get file content at parent", "file", file, "err", err)
				continue
			}
			formatterToUse = r.pickFormatter(ctx, prev) // pick the strictest formatter that passes on the original version
		}

		// Apply the chosen formatter to the current file
		newCode := r.runFormatter(ctx, formatterToUse, code)
		if newCode == nil { // no changes made
			continue
		}
		// write to disk
		if err := os.WriteFile(file, newCode, 0o600); err != nil {
			slog.WarnContext(ctx, "CodeReviewer.Autoformat unable to write formatted file", "file", file, "err", err)
			continue
		}
		fmtFiles = append(fmtFiles, file)
	}
	return fmtFiles
}

// RequireNormalGitState checks that the git repo state is pretty normal.
func (r *CodeReviewer) RequireNormalGitState(_ context.Context) error {
	rebaseDirs := []string{"rebase-merge", "rebase-apply"}
	for _, dir := range rebaseDirs {
		_, err := os.Stat(filepath.Join(r.repoRoot, dir))
		if err == nil {
			return fmt.Errorf("git repo is not clean: rebase in progress")
		}
	}
	filesReason := map[string]string{
		"MERGE_HEAD":       "merge is in progress",
		"CHERRY_PICK_HEAD": "cherry-pick is in progress",
		"REVERT_HEAD":      "revert is in progress",
		"BISECT_LOG":       "bisect is in progress",
	}
	for file, reason := range filesReason {
		_, err := os.Stat(filepath.Join(r.repoRoot, file))
		if err == nil {
			return fmt.Errorf("git repo is not clean: %s", reason)
		}
	}
	return nil
}

func (r *CodeReviewer) RequireNoUncommittedChanges(ctx context.Context) error {
	// Check that there are no uncommitted changes, whether staged or not.
	// (Changes in r.initialStatus are OK, no other changes are.)
	statuses, err := r.repoStatus(ctx)
	if err != nil {
		return fmt.Errorf("unable to get repo status: %w", err)
	}
	uncommitted := new(strings.Builder)
	for _, status := range statuses {
		if !r.initialStatusesContainFile(status.Path) {
			fmt.Fprintf(uncommitted, "%s %s\n", status.Path, status.RawStatus)
		}
	}
	if uncommitted.Len() > 0 {
		return fmt.Errorf("uncommitted changes in repo, please commit or revert:\n%s", uncommitted.String())
	}
	return nil
}

func (r *CodeReviewer) initialStatusesContainFile(file string) bool {
	for _, s := range r.initialStatus {
		if s.Path == file {
			return true
		}
	}
	return false
}

type fileStatus struct {
	Path      string
	RawStatus string // always 2 characters
}

func (r *CodeReviewer) repoStatus(ctx context.Context) ([]fileStatus, error) {
	// Run git status --porcelain, split into lines
	cmd := exec.CommandContext(ctx, "git", "status", "--porcelain")
	cmd.Dir = r.repoRoot
	out, err := cmd.CombinedOutput()
	if err != nil {
		return nil, fmt.Errorf("failed to run git status: %w\n%s", err, out)
	}
	var statuses []fileStatus
	for line := range strings.Lines(string(out)) {
		if len(line) == 0 {
			continue
		}
		if len(line) < 3 {
			return nil, fmt.Errorf("invalid status line: %s", line)
		}
		path := line[3:]
		status := line[:2]
		absPath := r.absPath(path)
		statuses = append(statuses, fileStatus{Path: absPath, RawStatus: status})
	}
	return statuses, nil
}

// CurrentCommit retrieves the current git commit hash
func (r *CodeReviewer) CurrentCommit(ctx context.Context) (string, error) {
	return r.ResolveCommit(ctx, "HEAD")
}

func (r *CodeReviewer) ResolveCommit(ctx context.Context, ref string) (string, error) {
	cmd := exec.CommandContext(ctx, "git", "rev-parse", ref)
	cmd.Dir = r.repoRoot
	out, err := cmd.CombinedOutput()
	if err != nil {
		return "", fmt.Errorf("failed to get current commit hash: %w\n%s", err, out)
	}
	return strings.TrimSpace(string(out)), nil
}

func (r *CodeReviewer) absPath(relPath string) string {
	return filepath.Clean(filepath.Join(r.repoRoot, relPath))
}

// gitFileStatus returns the status of a file (A for added, M for modified, D for deleted, etc.)
func (r *CodeReviewer) gitFileStatus(ctx context.Context, file string) (string, error) {
	cmd := exec.CommandContext(ctx, "git", "diff", "--name-status", r.initialCommit, "HEAD", "--", file)
	cmd.Dir = r.repoRoot
	out, err := cmd.CombinedOutput()
	if err != nil {
		return "", fmt.Errorf("failed to get file status: %w\n%s", err, out)
	}
	status := strings.TrimSpace(string(out))
	if status == "" {
		return "", fmt.Errorf("no status found for file: %s", file)
	}
	return string(status[0]), nil
}

// getFileContentAtCommit retrieves file content at a specific commit
func (r *CodeReviewer) getFileContentAtCommit(ctx context.Context, file, commit string) ([]byte, error) {
	relFile, err := filepath.Rel(r.repoRoot, file)
	if err != nil {
		slog.WarnContext(ctx, "CodeReviewer.getFileContentAtCommit: failed to get relative path", "repo_root", r.repoRoot, "file", file, "err", err)
		file = relFile
	}
	cmd := exec.CommandContext(ctx, "git", "show", fmt.Sprintf("%s:%s", commit, relFile))
	cmd.Dir = r.repoRoot
	out, err := cmd.CombinedOutput()
	if err != nil {
		return nil, fmt.Errorf("failed to get file content at commit %s: %w\n%s", commit, err, out)
	}
	return out, nil
}

// runFormatter runs the specified formatter on a file and returns the results.
// A nil result indicates that the file is unchanged, or that an error occurred.
func (r *CodeReviewer) runFormatter(ctx context.Context, formatter string, content []byte) []byte {
	if formatter == "" {
		return nil // no formatter
	}
	// Run the formatter and capture the output
	cmd := exec.CommandContext(ctx, formatter)
	cmd.Dir = r.repoRoot
	cmd.Stdin = bytes.NewReader(content)
	out, err := cmd.CombinedOutput()
	if err != nil {
		// probably a parse error, err on the side of safety
		return nil
	}
	if bytes.Equal(content, out) {
		return nil // no changes
	}
	return out
}

// formatterWouldChange reports whether a formatter would make changes to the content.
// If the contents are invalid, it returns false.
// It works by piping the content to the formatter with the -l flag.
func (r *CodeReviewer) formatterWouldChange(ctx context.Context, formatter string, content []byte) bool {
	cmd := exec.CommandContext(ctx, formatter, "-l")
	cmd.Dir = r.repoRoot
	cmd.Stdin = bytes.NewReader(content)
	out, err := cmd.CombinedOutput()
	if err != nil {
		// probably a parse error, err on the side of safety
		return false
	}

	// If the output is empty, the file passes the formatter
	// If the output contains "<standard input>", the file would be changed
	return len(bytes.TrimSpace(out)) > 0
}

// pickFormatter picks a formatter to use for code.
// If something goes wrong, it recommends no formatter (empty string).
func (r *CodeReviewer) pickFormatter(ctx context.Context, code []byte) string {
	// Test each formatter from strictest to least strict.
	// Keep the first one that doesn't make changes.
	formatters := []string{"gofumpt", "goimports", "gofmt"}
	for _, formatter := range formatters {
		if r.formatterWouldChange(ctx, formatter, code) {
			continue
		}
		return formatter
	}
	return "" // no safe formatter found
}

// changedFiles retrieves a list of all files changed between two commits
func (r *CodeReviewer) changedFiles(ctx context.Context, fromCommit, toCommit string) ([]string, error) {
	cmd := exec.CommandContext(ctx, "git", "diff", "--name-only", fromCommit, toCommit)
	cmd.Dir = r.repoRoot
	out, err := cmd.CombinedOutput()
	if err != nil {
		return nil, fmt.Errorf("failed to get changed files: %w\n%s", err, out)
	}
	var files []string
	for line := range strings.Lines(string(out)) {
		line = strings.TrimSpace(line)
		if len(line) == 0 {
			continue
		}
		path := r.absPath(line)
		if r.initialStatusesContainFile(path) {
			continue
		}
		files = append(files, path)
	}
	return files, nil
}

// ModTidy runs go mod tidy.
func (r *CodeReviewer) ModTidy(ctx context.Context) error {
	err := r.requireHEADDescendantOfInitialCommit(ctx)
	if err != nil {
		return fmt.Errorf("cannot run ModTidy: %w", err)
	}

	cmd := exec.CommandContext(ctx, "go", "mod", "tidy")
	cmd.Dir = r.repoRoot
	out, err := cmd.CombinedOutput()
	if err != nil {
		return fmt.Errorf("go mod tidy failed: %w\n%s", err, out)
	}

	return nil
}

// RunMechanicalChecks runs all mechanical checks and returns a message describing any changes made.
func (r *CodeReviewer) RunMechanicalChecks(ctx context.Context) string {
	var actions []string

	changed := r.autoformat(ctx)
	if len(changed) > 0 {
		actions = append(actions, "autoformatters")
	}

	err := r.ModTidy(ctx)
	if err != nil {
		slog.WarnContext(ctx, "CodeReviewer.RunMechanicalChecks: ModTidy failed", "err", err)
	} else {
		// Figure out which files go mod tidy changed, best effort.
		// TODO: if we knew the repo was clean going in, this would be easier.
		statusCmd := exec.CommandContext(ctx, "git", "status", "--porcelain")
		statusCmd.Dir = r.repoRoot
		statusOut, err := statusCmd.CombinedOutput()
		if err != nil {
			slog.WarnContext(ctx, "CodeReviewer.RunMechanicalChecks: unable to get git status", "err", err)
			return ""
		}

		madeChanges := false
		for line := range strings.Lines(string(statusOut)) {
			if len(line) <= 3 {
				// empty line, defensiveness to avoid panics
				continue
			}
			file := line[3:]
			// TODO: this is a rough heuristic, revisit
			if !strings.Contains(file, "go.") {
				continue
			}
			path := filepath.Join(r.repoRoot, file)
			changed = append(changed, path)
			madeChanges = true
		}
		if madeChanges {
			actions = append(actions, "`go mod tidy`")
		}
	}

	if len(changed) == 0 {
		return ""
	}

	slices.Sort(changed)

	msg := fmt.Sprintf(`I ran %s, which updated these files:

%s

Please amend your latest git commit with these changes and then continue with what you were doing.`,
		strings.Join(actions, " and "),
		strings.Join(changed, "\n"),
	)

	return msg
}
