package bindingmanage

import (
	"errors"

	"github.com/tidbcloud/AgentTeam/internal/store/storeerr"
)

type ErrorCode string

const (
	ErrorCodeInvalidRequest      ErrorCode = "binding_invalid_request"
	ErrorCodeNotFound            ErrorCode = "binding_not_found"
	ErrorCodeRevisionConflict    ErrorCode = "binding_revision_conflict"
	ErrorCodeIdempotencyConflict ErrorCode = "binding_idempotency_conflict"
	ErrorCodeArchived            ErrorCode = "binding_archived"
	ErrorCodeInvalidState        ErrorCode = "binding_invalid_state"
	ErrorCodePlanArchived        ErrorCode = "binding_plan_archived"
	ErrorCodePlanNotFound        ErrorCode = "binding_plan_not_found"
	ErrorCodePlanVersionInvalid  ErrorCode = "binding_plan_version_invalid"
	ErrorCodeValidationFailed    ErrorCode = "binding_validation_failed"
	ErrorCodeForbidden           ErrorCode = "binding_forbidden"
	ErrorCodeConflict            ErrorCode = "binding_conflict"
)

type RequestError struct {
	Kind    error
	Code    ErrorCode
	Message string
	Details any
	Cause   error
}

func (err RequestError) Error() string { return err.Message }

// Unwrap returns the declared store kind only. The declared Kind is
// authoritative for public status/code classification: the internal Cause is
// preserved separately (InternalCause) for logs and structured logging and
// never participates in the errors.Is/As graph consumed by publicerr, so an
// internal cause that itself carries a store sentinel can never override the
// declared kind.
func (err RequestError) Unwrap() error { return err.Kind }

// InternalCause returns the originating repository error retained exclusively
// for logs and wrapping, or nil. It is deliberately not part of the Unwrap
// chain.
func (err RequestError) InternalCause() error { return err.Cause }

// WorkflowPublicError implements publicerr.DomainError so the centralized
// Workflow error classifier can extract the stable code and structured details
// without importing this domain package.
func (err RequestError) WorkflowPublicError() (string, any) {
	return string(err.Code), err.Details
}

type RevisionConflictDetails struct {
	Resource         string `json:"resource"`
	ExpectedRevision int64  `json:"expectedRevision"`
	CurrentRevision  int64  `json:"currentRevision"`
}

func ErrorDetails(err error) (ErrorCode, any, bool) {
	var requestError RequestError
	if !errors.As(err, &requestError) {
		return "", nil, false
	}
	return requestError.Code, requestError.Details, true
}

func invalidRequest(message string) error {
	return RequestError{Kind: storeerr.ErrBadRequest, Code: ErrorCodeInvalidRequest, Message: message}
}

func validationFailed(diagnostic Diagnostic) error {
	return RequestError{
		Kind: storeerr.ErrUnprocessable, Code: ErrorCodeValidationFailed,
		Message: diagnostic.Message, Details: map[string]any{"diagnostics": []Diagnostic{diagnostic}},
	}
}
