package tenants

import (
	"context"
	"fmt"
	"io"

	"github.com/tidbcloud/observability/vm-migration/internal/printer"
)

// DeletedCluster identifies one deleted cluster for an exact-key archive
// lookup; the essential s3 stage derives these from its cluster report.
type DeletedCluster struct {
	ClusterID      string `json:"clusterId"`
	ClusterName    string `json:"clusterName"`
	ProjectID      string `json:"projectId"`
	OrganizationID string `json:"organizationId"`
}

// S3Fetcher abstracts the per-cluster yaml fetch so tests inject fakes
// without spawning aws.
type S3Fetcher interface {
	Fetch(ctx context.Context, bucket, key string) (string, error)
}

// awsCLIFetcher runs `aws s3 cp s3://bucket/key -` and returns stdout.
type awsCLIFetcher struct{}

// NewAWSCLIFetcher returns the production S3Fetcher (shells out to aws).
func NewAWSCLIFetcher() S3Fetcher { return &awsCLIFetcher{} }

func (f *awsCLIFetcher) Fetch(ctx context.Context, bucket, key string) (string, error) {
	uri := "s3://" + bucket + "/" + key
	return runCLI(ctx, AWSExecutable, []string{"s3", "cp", uri, "-"}, uri)
}

// fetchArchivedEntry fetches and parses one cluster's archived cluster.yaml.
//
// Logs a SKIP line and returns nil when the object is missing, fails to
// parse, or does not match bizType; logs OK and returns the entry otherwise.
func fetchArchivedEntry(
	ctx context.Context,
	fetcher S3Fetcher,
	bucket, bizType string,
	c DeletedCluster,
	prefix string,
	stderr io.Writer,
) *Entry {
	key := clusterS3Key(bizType, c)
	text, err := fetcher.Fetch(ctx, bucket, key)
	if err != nil {
		printer.Printf(stderr, "%s -> SKIP (no cluster.yaml: %v)", prefix, err)
		return nil
	}
	entry, err := ParseClusterYAML(text, []string{bizType}, SourceS3)
	if err != nil || entry == nil {
		printer.Printf(stderr, "%s -> SKIP (yaml biztype != %s or tenant missing: %v)", prefix, bizType, err)
		return nil
	}
	printer.Printf(stderr, "%s -> OK tenant=%s", prefix, entry.Tenant)
	return entry
}

// clusterS3Key builds the exact S3 key for one cluster.yaml.
//
// Format: archived/<bizType>/<orgId>/<projectId>/<clusterId>/cluster.yaml
func clusterS3Key(bizType string, c DeletedCluster) string {
	return fmt.Sprintf("archived/%s/%s/%s/%s/cluster.yaml",
		bizType, c.OrganizationID, c.ProjectID, c.ClusterID)
}
