package automation

import (
	"context"
	"errors"
	"fmt"
	"strings"

	"github.com/tidbcloud/AgentTeam/internal/store/resource/repos"
	"gorm.io/gorm"
)

const automationRepositoryOwnerKind = "automation_repository"

func (s *AutomationsService) bindAutomationRepository(ctx context.Context, workspaceID string, subject string, owner string, repo string, defaultRef string) error {
	if s == nil || s.repositoryStore == nil {
		return nil
	}
	workspaceID = strings.TrimSpace(workspaceID)
	owner = strings.TrimSpace(owner)
	repo = strings.TrimSpace(repo)
	if workspaceID == "" || owner == "" || repo == "" {
		return nil
	}
	repoFullName := owner + "/" + repo
	resourceID := repos.AutomationRepositoryResourceID(repoFullName)
	defaultRef = normalizeAutomationRepositoryBindingDefaultRef(defaultRef)
	now := s.now()
	actor := strings.TrimSpace(subject)
	if actor == "" {
		actor = "system"
	}
	binding := repos.ResourceRepository{
		ID:           repos.ResourceRepositoryBindingID(workspaceID, repos.ResourceTypeAutomationRepository, resourceID, repos.RepoRolePrimary),
		WorkspaceID:  workspaceID,
		ResourceType: repos.ResourceTypeAutomationRepository,
		ResourceID:   resourceID,
		RepoRole:     repos.RepoRolePrimary,
		OwnerKind:    automationRepositoryOwnerKind,
		RepoOwner:    owner,
		RepoName:     repo,
		RepoFullName: repoFullName,
		DefaultRef:   defaultRef,
		Visibility:   "private",
		UserVisible:  true,
		CreatedBy:    actor,
		UpdatedBy:    actor,
		CreatedAt:    now,
		UpdatedAt:    now,
	}
	existing, err := s.repositoryStore.Get(ctx, workspaceID, repos.ResourceTypeAutomationRepository, resourceID, repos.RepoRolePrimary)
	switch {
	case err == nil:
		binding.ID = existing.ID
		binding.AGSRepoID = existing.AGSRepoID
		binding.Visibility = firstNonEmptyString(existing.Visibility, binding.Visibility)
		binding.UserVisible = existing.UserVisible || binding.UserVisible
		binding.CreatedBy = firstNonEmptyString(existing.CreatedBy, binding.CreatedBy)
		binding.CreatedAt = existing.CreatedAt
		if binding.DefaultRef == "" {
			binding.DefaultRef = existing.DefaultRef
		}
	case errors.Is(err, gorm.ErrRecordNotFound):
	default:
		return fmt.Errorf("get automation repository mapping: %w", err)
	}
	_, err = s.repositoryStore.Upsert(ctx, binding)
	if err != nil {
		return fmt.Errorf("upsert automation repository mapping: %w", err)
	}
	return nil
}

func normalizeAutomationRepositoryBindingDefaultRef(value string) string {
	value = strings.TrimSpace(value)
	switch {
	case value == "", strings.EqualFold(value, "HEAD"), isCommitSHA(value):
		return ""
	case strings.HasPrefix(value, "refs/heads/"):
		return strings.TrimSpace(strings.TrimPrefix(value, "refs/heads/"))
	default:
		return value
	}
}
