package execution

import (
	"errors"

	executionstore "github.com/tidbcloud/AgentTeam/internal/store/role/execution"
	"github.com/tidbcloud/AgentTeam/internal/store/storeerr"
)

type ErrorKind string

const (
	ErrorDependency     ErrorKind = "dependency"
	ErrorInvalidRequest ErrorKind = "invalid_request"
	ErrorInvalidState   ErrorKind = "invalid_state"
	ErrorForbidden      ErrorKind = "forbidden"
	ErrorNotFound       ErrorKind = "not_found"
	ErrorConflict       ErrorKind = "conflict"
)

// ClassifyError keeps store-specific errors inside the Role service boundary.
func ClassifyError(err error) (ErrorKind, bool) {
	if kind, ok := classifyDeterministicApplyError(err); ok {
		return kind, true
	}
	switch {
	case IsRoleReadDependencyError(err):
		return ErrorDependency, true
	case IsRoleReadInputError(err), errors.Is(err, storeerr.ErrBadRequest):
		return ErrorInvalidRequest, true
	case errors.Is(err, ErrInvariant), errors.Is(err, storeerr.ErrUnprocessable):
		return ErrorInvalidState, true
	case errors.Is(err, ErrForbidden), errors.Is(err, storeerr.ErrForbidden):
		return ErrorForbidden, true
	case errors.Is(err, storeerr.ErrNotFound),
		errors.Is(err, executionstore.ErrNotFound):
		return ErrorNotFound, true
	case errors.Is(err, ErrConflict), errors.Is(err, storeerr.ErrConflict):
		return ErrorConflict, true
	default:
		return "", false
	}
}

func classifyDeterministicApplyError(err error) (ErrorKind, bool) {
	var applyErr *ApplyError
	if !errors.As(err, &applyErr) || applyErr == nil {
		return "", false
	}
	switch applyErr.Outcome {
	case ApplyInvalidRequest:
		return ErrorInvalidRequest, true
	case ApplyAuthorityDenied:
		return ErrorForbidden, true
	case ApplyNotFound:
		return ErrorNotFound, true
	case ApplyVersionConflict, ApplyOperationConflict:
		return ErrorConflict, true
	default:
		return "", false
	}
}
