package git_test

import (
	"testing"

	gitcontract "bit.admedia.com/scm/ad/adpilot-indexing-repo-sync.com/internal/contracts/git"
	"bit.admedia.com/scm/ad/adpilot-indexing-repo-sync.com/internal/contracts/events"
	"bit.admedia.com/scm/ad/adpilot-indexing-repo-sync.com/internal/git"
)

func TestParseNameStatus(t *testing.T) {
	output := "A\tinternal/new.go\nM\tREADME.md\nD\told.txt\nR100\told/name.go\tnew/name.go\n"
	changes, err := git.ParseNameStatus(output)
	if err != nil {
		t.Fatalf("ParseNameStatus: %v", err)
	}
	if len(changes) != 4 {
		t.Fatalf("got %d changes, want 4", len(changes))
	}

	assertChange(t, changes[0], events.ChangeTypeAdded, "internal/new.go", "")
	assertChange(t, changes[1], events.ChangeTypeModified, "README.md", "")
	assertChange(t, changes[2], events.ChangeTypeDeleted, "old.txt", "")
	assertChange(t, changes[3], events.ChangeTypeRenamed, "new/name.go", "old/name.go")
}

func TestParseCommitLog(t *testing.T) {
	output := commitLogFixture(
		"abc123", "def456",
		"Alice", "alice@example.com", "2026-06-01T10:00:00+00:00",
		"Bob", "bob@example.com", "2026-06-01T11:00:00+00:00",
		"First commit\n\nBody line",
	) + commitLogFixture(
		"789abc", "",
		"Carol", "carol@example.com", "2026-06-02T10:00:00+00:00",
		"Carol", "carol@example.com", "2026-06-02T10:00:00+00:00",
		"Root commit",
	)
	commits := git.ParseCommitLog(output)
	if len(commits) != 2 {
		t.Fatalf("got %d commits, want 2", len(commits))
	}
	if commits[0].CommitSHA != "abc123" || commits[0].ParentSHA != "def456" {
		t.Fatalf("unexpected first commit: %+v", commits[0])
	}
	if commits[0].AuthorName != "Alice" || commits[0].AuthorEmail != "alice@example.com" {
		t.Fatalf("unexpected author metadata: %+v", commits[0].GitCommitMetadata)
	}
	if commits[0].CommitMessage != "First commit\n\nBody line" {
		t.Fatalf("unexpected message: %q", commits[0].CommitMessage)
	}
	if commits[1].CommitSHA != "789abc" {
		t.Fatalf("unexpected second commit: %+v", commits[1])
	}
}

func commitLogFixture(
	sha, parent, authorName, authorEmail, authoredAt, committerName, committerEmail, committedAt, message string,
) string {
	return sha + "\x00" + parent + "\x00" + authorName + "\x00" + authorEmail + "\x00" +
		authoredAt + "\x00" + committerName + "\x00" + committerEmail + "\x00" +
		committedAt + "\x00" + message + "\x00"
}

func TestClassifyAllFiles(t *testing.T) {
	changes := git.ClassifyAllFiles([]string{"main.go", "docs/readme.md"})
	if len(changes) != 2 {
		t.Fatalf("got %d changes, want 2", len(changes))
	}
	if changes[0].ChangeType != events.ChangeTypeAdded {
		t.Fatalf("expected added change type, got %q", changes[0].ChangeType)
	}
}

func assertChange(t *testing.T, change gitcontract.FileChange, changeType events.ChangeType, path, oldPath string) {
	t.Helper()
	if change.ChangeType != changeType {
		t.Errorf("change_type: got %q, want %q", change.ChangeType, changeType)
	}
	if change.Path != path {
		t.Errorf("path: got %q, want %q", change.Path, path)
	}
	if change.OldPath != oldPath {
		t.Errorf("old_path: got %q, want %q", change.OldPath, oldPath)
	}
}
