package mcp

import (
	
	
	
)

// Sentinel errors for common JSON-RPC error codes.
var (
	// ErrParseError indicates a JSON parsing error (code: PARSE_ERROR).
	ErrParseError = errors.New("parse error")

	// ErrInvalidRequest indicates an invalid JSON-RPC request (code: INVALID_REQUEST).
	ErrInvalidRequest = errors.New("invalid request")

	// ErrMethodNotFound indicates the requested method does not exist (code: METHOD_NOT_FOUND).
	ErrMethodNotFound = errors.New("method not found")

	// ErrInvalidParams indicates invalid method parameters (code: INVALID_PARAMS).
	ErrInvalidParams = errors.New("invalid params")

	// ErrInternalError indicates an internal JSON-RPC error (code: INTERNAL_ERROR).
	ErrInternalError = errors.New("internal error")

	// ErrRequestInterrupted indicates a request was cancelled or timed out (code: REQUEST_INTERRUPTED).
	ErrRequestInterrupted = errors.New("request interrupted")

	// ErrResourceNotFound indicates a requested resource was not found (code: RESOURCE_NOT_FOUND).
	ErrResourceNotFound = errors.New("resource not found")
)

// URLElicitationRequiredError is returned when the server requires URL elicitation to proceed.
type URLElicitationRequiredError struct {
	Elicitations []ElicitationParams `json:"elicitations"`
}

func ( URLElicitationRequiredError) () string {
	return fmt.Sprintf("URL elicitation required: %d elicitation(s) needed", len(.Elicitations))
}

func ( URLElicitationRequiredError) () JSONRPCError {
	return JSONRPCError{
		JSONRPC: JSONRPC_VERSION,
		Error: JSONRPCErrorDetails{
			Code:    URL_ELICITATION_REQUIRED,
			Message: .Error(),
			Data: map[string]any{
				"elicitations": .Elicitations,
			},
		},
	}
}

// UnsupportedProtocolVersionError is returned when the server responds with
// a protocol version that the client doesn't support.
type UnsupportedProtocolVersionError struct {
	Version string
}

func ( UnsupportedProtocolVersionError) () string {
	return fmt.Sprintf("unsupported protocol version: %q", .Version)
}

// Is implements the errors.Is interface for better error handling
func ( URLElicitationRequiredError) ( error) bool {
	,  := .(URLElicitationRequiredError)
	return 
}

// Is implements the errors.Is interface for better error handling
func ( UnsupportedProtocolVersionError) ( error) bool {
	,  := .(UnsupportedProtocolVersionError)
	return 
}

// IsUnsupportedProtocolVersion checks if an error is an UnsupportedProtocolVersionError
func ( error) bool {
	,  := .(UnsupportedProtocolVersionError)
	return 
}

// AsError maps JSONRPCErrorDetails to a Go error.
// Returns sentinel errors wrapped with custom messages for known codes.
// Defaults to a generic error with the original message when the code is not mapped.
func ( *JSONRPCErrorDetails) () error {
	var  error

	switch .Code {
	case PARSE_ERROR:
		 = ErrParseError
	case INVALID_REQUEST:
		 = ErrInvalidRequest
	case METHOD_NOT_FOUND:
		 = ErrMethodNotFound
	case INVALID_PARAMS:
		 = ErrInvalidParams
	case INTERNAL_ERROR:
		 = ErrInternalError
	case REQUEST_INTERRUPTED:
		 = ErrRequestInterrupted
	case RESOURCE_NOT_FOUND:
		 = ErrResourceNotFound
	case URL_ELICITATION_REQUIRED:
		// Attempt to reconstruct URLElicitationRequiredError from Data
		if .Data != nil {
			// Round-trip through JSON to parse into struct
			// This handles both map[string]any (from unmarshal) and other forms
			if ,  := json.Marshal(.Data);  == nil {
				var  struct {
					 []ElicitationParams `json:"elicitations"`
				}
				if  := json.Unmarshal(, &);  == nil {
					return URLElicitationRequiredError{
						Elicitations: .,
					}
				}
			}
		}
		// Fallback if data is missing or invalid
		return URLElicitationRequiredError{}
	default:
		return errors.New(.Message)
	}

	// Wrap the sentinel error with the custom message if it differs from the sentinel.
	if .Message != "" && .Message != .Error() {
		return fmt.Errorf("%w: %s", , .Message)
	}

	return 
}