package service_test

import (
	"context"
	"os"
	"testing"
	"time"

	"github.com/pingcap/agent-git-service/internal/db"
	"github.com/pingcap/agent-git-service/internal/service"
	"github.com/pingcap/agent-git-service/internal/testharness"
)

func writeRepositoryFileFixture(t testing.TB, svc *service.Service, ctx context.Context, fullName, branch, path, message string, content []byte) (string, error) {
	return testharness.WriteRepositoryFile(t, svc, ctx, fullName, branch, path, message, content)
}

func createRepositoryBranchFixture(t testing.TB, svc *service.Service, ctx context.Context, fullName, branch, fromBranch string) error {
	return testharness.CreateRepositoryBranch(t, svc, ctx, fullName, branch, fromBranch)
}

func createRepositoryTagFixture(t testing.TB, svc *service.Service, ctx context.Context, fullName, tagName, message, sha string) error {
	return testharness.CreateRepositoryTag(t, svc, ctx, fullName, tagName, message, sha)
}

func deleteRepositoryRefFixture(t testing.TB, svc *service.Service, ctx context.Context, fullName, ref string) error {
	return testharness.DeleteRepositoryRef(t, svc, ctx, fullName, ref)
}

func setRepositoryRefFixture(t testing.TB, svc *service.Service, ctx context.Context, fullName, ref, sha string) error {
	return testharness.SetRepositoryRef(t, svc, ctx, fullName, ref, sha)
}

func initializeBareRepositoryFixture(svc *service.Service, ctx context.Context, fullName, defaultBranch string, seed bool) error {
	return testharness.InitializeBareRepositoryFixture(ctx, svc.Git, fullName, defaultBranch, seed)
}

func removeGitRepositoryFixture(t testing.TB, svc *service.Service, ctx context.Context, fullName string) {
	t.Helper()
	path, err := svc.Git.GetRepoPath(ctx, fullName)
	if err != nil {
		t.Fatalf("resolve git repository fixture %s: %v", fullName, err)
	}
	if err := os.RemoveAll(path); err != nil {
		t.Fatalf("remove git repository fixture %s: %v", fullName, err)
	}
}

// setupTestService builds a bare service backed by TiDB + temp gitstore.
// Thin wrapper over testharness.NewService to preserve the existing call-site
// signature across hundreds of service-layer tests.
func setupTestService(t testing.TB) (*service.Service, func()) {
	return testharness.NewService(t, testharness.ServiceConfig{})
}

func mustAddOrgMember(t testing.TB, svc *service.Service, orgID, userID uint, role string) {
	t.Helper()
	if err := svc.AddOrgMember(context.Background(), orgID, userID, role); err != nil {
		t.Fatalf("AddOrgMember(%d,%d,%s): %v", orgID, userID, role, err)
	}
}

// setupRepoForTest creates a user and repo for use in service tests.
func setupRepoForTest(t testing.TB, svc *service.Service, login, repoName string) {
	t.Helper()
	svc.DB.Create(&db.User{Login: login, Name: login, Type: db.TypeUser})
	_, err := svc.CreateRepo(context.Background(), service.CreateRepoInput{OwnerLogin: login, Name: repoName})
	if err != nil {
		t.Fatalf("setupRepoForTest failed: %v", err)
	}
}

func testWorkflowRunJob(runID uint, name string) db.WorkflowRunJob {
	now := time.Now()
	return db.WorkflowRunJob{
		RunID:       runID,
		Name:        name,
		Status:      db.RunCompleted,
		Conclusion:  db.ConclusionSuccess,
		StartedAt:   now,
		CompletedAt: now,
	}
}

func testActionCache(repoID uint, key, ref, version string) db.ActionCache {
	return db.ActionCache{
		RepositoryID:   repoID,
		Key:            key,
		Ref:            ref,
		Version:        version,
		LastAccessedAt: time.Now(),
	}
}
