package binding

import (
	"encoding/json"
	"net/http"
	"strconv"
	"strings"

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

func requestActor(request api.WorkspaceScopedRequest) Actor {
	return Actor{Type: ActorTypeHuman, ID: strings.TrimSpace(request.UserID()), MemberID: strings.TrimSpace(request.Workspace.MemberID)}
}

func requestOwner(request api.WorkspaceScopedRequest) Owner {
	return Owner{UserID: strings.TrimSpace(request.UserID()), MemberID: strings.TrimSpace(request.Workspace.MemberID)}
}

func bindingID(request api.WorkspaceScopedRequest) (string, error) {
	value := strings.TrimSpace(request.Gin.Param("bindingId"))
	if value == "" {
		return "", publicError(http.StatusBadRequest, "binding_id_required", "bindingId is required")
	}
	return value, nil
}

func revisionNumber(request api.WorkspaceScopedRequest) (int64, error) {
	value, err := strconv.ParseInt(strings.TrimSpace(request.Gin.Param("revision")), 10, 64)
	if err != nil || value < 1 {
		return 0, publicError(http.StatusBadRequest, "binding_invalid_revision", "revision must be a positive integer")
	}
	return value, nil
}

func pageLimit(request api.WorkspaceScopedRequest) (int, error) {
	raw := strings.TrimSpace(request.Gin.Query("limit"))
	if raw == "" {
		return 0, nil
	}
	value, err := strconv.Atoi(raw)
	if err != nil || value < 1 || value > 100 {
		return 0, publicError(http.StatusBadRequest, "binding_invalid_limit", "limit must be between 1 and 100")
	}
	return value, nil
}

func includeArchived(request api.WorkspaceScopedRequest) bool {
	switch strings.ToLower(strings.TrimSpace(request.Gin.Query("includeArchived"))) {
	case "1", "true", "yes":
		return true
	default:
		return false
	}
}

func requiredRevisionSpec(planVersionID string, source json.RawMessage, inputPolicy json.RawMessage) (string, json.RawMessage, json.RawMessage, error) {
	planVersionID = strings.TrimSpace(planVersionID)
	if planVersionID == "" {
		return "", nil, nil, publicError(http.StatusBadRequest, "binding_invalid_request", "planVersionId is required")
	}
	if len(source) == 0 || string(source) == "null" {
		return "", nil, nil, publicError(http.StatusBadRequest, "binding_invalid_request", "source is required")
	}
	if len(inputPolicy) == 0 || string(inputPolicy) == "null" {
		inputPolicy = json.RawMessage(`{}`)
	}
	return planVersionID, source, inputPolicy, nil
}

func requiredPlanID(planID string) (string, error) {
	planID = strings.TrimSpace(planID)
	if planID == "" {
		return "", publicError(http.StatusBadRequest, "binding_invalid_request", "planId is required")
	}
	return planID, nil
}

func bindingMutationPreconditions(request api.WorkspaceScopedRequest) (string, int64, error) {
	id, err := bindingID(request)
	if err != nil {
		return "", 0, err
	}
	revision, err := requireBindingRevision(request.Gin.GetHeader("If-Match"), id)
	if err != nil {
		return "", 0, err
	}
	return id, revision, nil
}
