package archive

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

	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

	workflowarchivepkg "github.com/argoproj/argo-workflows/v4/pkg/apiclient/workflowarchive"
	"github.com/argoproj/argo-workflows/v4/util/humanize"
)

// uuidRegex matches Kubernetes UID format (RFC 4122 UUID)
// Example: a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11
var uuidRegex = regexp.MustCompile(`^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$`)

// isUID returns true if the input string matches the UUID format used by Kubernetes UIDs
func isUID(s string, forceUID bool, forceName bool) bool {
	if forceUID {
		return true
	}
	if forceName {
		return false
	}
	return uuidRegex.MatchString(s)
}

func resolveUID(ctx context.Context, serviceClient workflowarchivepkg.ArchivedWorkflowServiceClient, identifier string, namespace string, forceUID bool, forceName bool) (string, error) {
	if isUID(identifier, forceUID, forceName) {
		return identifier, nil
	}

	req := &workflowarchivepkg.ListArchivedWorkflowsRequest{
		Namespace:  namespace,
		NamePrefix: identifier,
		NameFilter: "Exact",
	}

	resp, err := serviceClient.ListArchivedWorkflows(ctx, req)
	if err != nil {
		return "", fmt.Errorf("list archived workflows: %w", err)
	}

	matches := resp.Items
	for len(matches) < 2 && resp.Continue != "" {
		req.ListOptions = &metav1.ListOptions{Continue: resp.Continue}
		resp, err = serviceClient.ListArchivedWorkflows(ctx, req)
		if err != nil {
			return "", fmt.Errorf("list archived workflows: %w", err)
		}
		matches = append(matches, resp.Items...)
	}

	if len(matches) == 0 {
		return "", fmt.Errorf("archived workflow '%s' not found", identifier)
	}

	if len(matches) > 1 {
		var msg strings.Builder
		fmt.Fprintf(&msg, "Multiple archived workflows found with name '%s':\n", identifier)
		for _, wf := range matches {
			fmt.Fprintf(&msg, "  %s (Created: %s, Finished: %s)\n", wf.UID, humanize.Timestamp(wf.CreationTimestamp.Time), humanize.Timestamp(wf.Status.FinishedAt.Time))
		}
		msg.WriteString("Please specify the UID.")
		return "", errors.New(msg.String())
	}

	return string(matches[0].UID), nil
}
