package provider

import (
	"context"
	"fmt"
	"strings"
	"time"

	"github.com/tidbcloud/AgentTeam/internal/coredb"
)

const (
	githubAppDefinitionID               = "app_github"
	githubAppServiceKind                = "app"
	githubSetupVerifyingRequestStatus   = "setup_verifying"
	githubSetupPatchingRequestStatus    = "setup_patching"
	githubSetupVerificationLeaseTimeout = 5 * time.Minute
)

// fenceGitHubProviderMutationInTx shares the canonical App definition mutex
// with the App store's staged recovery protocol. Provider config/connection
// mutations therefore cannot slip between lease begin and its CAS finalize.
func fenceGitHubProviderMutationInTx(ctx context.Context, tx coredb.Tx, workspaceID string) error {
	var definitionID string
	if err := tx.QueryRow(ctx, `
SELECT id
FROM service_definitions
WHERE id = $1
  AND service_kind = $2
LIMIT 1
FOR UPDATE
`, githubAppDefinitionID, githubAppServiceKind).Scan(&definitionID); err != nil {
		if coredb.IsNotFound(err) {
			return ErrNotFound
		}
		return fmt.Errorf("lock GitHub setup mutation scope: %w", err)
	}
	if _, err := tx.Exec(ctx, `
DELETE FROM service_installation_requests
WHERE workspace_id = $1
  AND service_definition_id = $2
  AND service_kind = $3
  AND request_kind = 'install'
  AND status = $4
  AND created_at < $5
`, strings.TrimSpace(workspaceID), githubAppDefinitionID, githubAppServiceKind,
		githubSetupVerifyingRequestStatus, time.Now().UTC().Add(-githubSetupVerificationLeaseTimeout)); err != nil {
		return fmt.Errorf("delete expired GitHub setup verification: %w", err)
	}
	var leaseID string
	err := tx.QueryRow(ctx, `
SELECT id
FROM service_installation_requests
WHERE workspace_id = $1
  AND service_definition_id = $2
  AND service_kind = $3
  AND request_kind = 'install'
	  AND status IN ($4, $5)
	ORDER BY created_at ASC, id ASC
	LIMIT 1
	FOR UPDATE
`, strings.TrimSpace(workspaceID), githubAppDefinitionID, githubAppServiceKind,
		githubSetupVerifyingRequestStatus, githubSetupPatchingRequestStatus).Scan(&leaseID)
	if err != nil {
		if coredb.IsNotFound(err) {
			return nil
		}
		return fmt.Errorf("load GitHub setup verification: %w", err)
	}
	return conflict("GitHub setup verification is in progress for this workspace.")
}
