package testharness

import (
	"context"
	"fmt"
	"strings"
	"testing"

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

// WriteRepositoryFile arranges file content through the service-owned private
// mutation owner. A .wiki identity is accepted only as the exact sibling of
// the DB-backed base repository.
func WriteRepositoryFile(t testing.TB, svc *service.Service, ctx context.Context, fullName, branch, path, message string, content []byte) (string, error) {
	t.Helper()
	repository, err := svc.LookupRepoIdentity(ctx, fullName)
	if err != nil && strings.HasSuffix(fullName, ".wiki") {
		repository, err = svc.LookupRepoIdentity(ctx, strings.TrimSuffix(fullName, ".wiki"))
	}
	if err != nil {
		return "", err
	}
	if fullName != repository.FullName && fullName != repository.FullName+".wiki" {
		return "", fmt.Errorf("repository fixture identity mismatch: %s", fullName)
	}
	repository.FullName = fullName
	expectedBlobSHA, _ := svc.Git.BlobSHAAtRef(ctx, fullName, path, branch)
	return svc.WriteRepositoryFile(ctx, repository, branch, path, message, content, expectedBlobSHA)
}

// CreateRepositoryBranch arranges branch state through the service-owned
// mutation API instead of exposing a writable gitstore fixture surface.
func CreateRepositoryBranch(t testing.TB, svc *service.Service, ctx context.Context, fullName, branch, fromBranch string) error {
	t.Helper()
	repository, err := svc.LookupRepoIdentity(ctx, fullName)
	if err != nil {
		return err
	}
	return svc.CreateRepositoryBranch(ctx, repository.ID, repository.FullName, branch, fromBranch)
}

// CreateRepositoryTag arranges one annotated tag through the service-owned
// mutation API instead of exposing a writable gitstore fixture surface.
func CreateRepositoryTag(t testing.TB, svc *service.Service, ctx context.Context, fullName, tagName, message, sha string) error {
	t.Helper()
	repository, err := svc.LookupRepoIdentity(ctx, fullName)
	if err != nil {
		return err
	}
	return svc.CreateRepositoryTag(ctx, repository, tagName, message, sha)
}

// DeleteRepositoryRef arranges ref removal through the service-owned mutation
// API instead of exposing a writable gitstore fixture surface.
func DeleteRepositoryRef(t testing.TB, svc *service.Service, ctx context.Context, fullName, ref string) error {
	t.Helper()
	repository, err := svc.LookupRepoIdentity(ctx, fullName)
	if err != nil {
		return err
	}
	return svc.DeleteRepositoryRef(ctx, repository, ref)
}

// SetRepositoryRef arranges one exact ref through the service-owned mutation
// API instead of exposing a writable gitstore fixture surface.
func SetRepositoryRef(t testing.TB, svc *service.Service, ctx context.Context, fullName, ref, sha string) error {
	t.Helper()
	repository, err := svc.LookupRepoIdentity(ctx, fullName)
	if err != nil {
		return err
	}
	return svc.SetRepositoryRef(ctx, repository, ref, sha)
}
