package plan

import (
	"fmt"
	"net/http"
	"strconv"
	"strings"
)

const idempotencyHeader = "Idempotency-Key"

func planETag(planID string, revision int64) string {
	return fmt.Sprintf(`"workflow-plan:%s:%d"`, planID, revision)
}

func draftETag(planID string, revision int64) string {
	return fmt.Sprintf(`"workflow-plan-draft:%s:%d"`, planID, revision)
}

func requirePlanRevision(raw string, planID string) (int64, error) {
	return requireRevision(raw, "workflow-plan:"+strings.TrimSpace(planID)+":")
}

func requireDraftRevision(raw string, planID string) (int64, error) {
	return requireRevision(raw, "workflow-plan-draft:"+strings.TrimSpace(planID)+":")
}

func requireRevision(raw string, prefix string) (int64, error) {
	raw = strings.TrimSpace(raw)
	if raw == "" {
		return 0, publicError(http.StatusPreconditionRequired, "precondition_required", "If-Match is required")
	}
	if strings.HasPrefix(raw, "W/") || !strings.HasPrefix(raw, `"`) || !strings.HasSuffix(raw, `"`) {
		return 0, publicError(http.StatusBadRequest, "invalid_if_match", "If-Match must contain one strong Plan ETag")
	}
	if strings.Contains(raw, ",") {
		return 0, publicError(http.StatusBadRequest, "invalid_if_match", "If-Match must contain exactly one Plan ETag")
	}
	value := strings.TrimSuffix(strings.TrimPrefix(raw, `"`), `"`)
	if !strings.HasPrefix(value, prefix) {
		return 0, publicError(http.StatusBadRequest, "invalid_if_match", "If-Match is for the wrong Plan resource")
	}
	revision, err := strconv.ParseInt(strings.TrimPrefix(value, prefix), 10, 64)
	if err != nil || revision < 1 {
		return 0, publicError(http.StatusBadRequest, "invalid_if_match", "If-Match contains an invalid Plan revision")
	}
	return revision, nil
}
