package minio

import "errors"

// Common errors
var (
	ErrInvalidConfig      = errors.New("invalid configuration")
	ErrNotConnected       = errors.New("not connected to MinIO")
	ErrBucketNotFound     = errors.New("bucket not found")
	ErrObjectNotFound     = errors.New("object not found")
	ErrBucketAlreadyExists = errors.New("bucket already exists")
	ErrInvalidBucketName  = errors.New("invalid bucket name")
	ErrInvalidObjectName  = errors.New("invalid object name")
	ErrUploadFailed       = errors.New("upload failed")
	ErrDownloadFailed     = errors.New("download failed")
	ErrDeleteFailed       = errors.New("delete failed")
	ErrCopyFailed         = errors.New("copy failed")
	ErrMoveFailed         = errors.New("move failed")
	ErrInvalidRange       = errors.New("invalid range")
	ErrFileTooLarge       = errors.New("file too large")
	ErrInvalidFileType    = errors.New("invalid file type")
	ErrInvalidPath        = errors.New("invalid path")
	ErrAccessDenied       = errors.New("access denied")
	ErrTimeout            = errors.New("operation timeout")
	ErrInvalidCredentials = errors.New("invalid credentials")
	ErrConnectionFailed   = errors.New("connection failed")
	ErrPresignFailed      = errors.New("presigned URL generation failed")
)

// Error wraps errors with additional context
type Error struct {
	Code    string
	Message string
	Cause   error
}

// Error implements the error interface
func (e *Error) Error() string {
	if e.Cause != nil {
		return e.Message + ": " + e.Cause.Error()
	}
	return e.Message
}

// Unwrap returns the underlying error
func (e *Error) Unwrap() error {
	return e.Cause
}

// Wrap wraps an error with a message
func (e *Error) Wrap(msg string) *Error {
	return &Error{
		Code:    e.Code,
		Message: msg,
		Cause:   e,
	}
}

// NewError creates a new error with code and message
func NewError(code, message string) *Error {
	return &Error{
		Code:    code,
		Message: message,
	}
}

// NewErrorWithCause creates a new error with code, message and cause
func NewErrorWithCause(code, message string, cause error) *Error {
	return &Error{
		Code:    code,
		Message: message,
		Cause:   cause,
	}
}

// Error codes
const (
	ErrCodeInvalidConfig       = "INVALID_CONFIG"
	ErrCodeNotConnected        = "NOT_CONNECTED"
	ErrCodeBucketNotFound      = "BUCKET_NOT_FOUND"
	ErrCodeObjectNotFound      = "OBJECT_NOT_FOUND"
	ErrCodeBucketExists        = "BUCKET_EXISTS"
	ErrCodeInvalidBucketName   = "INVALID_BUCKET_NAME"
	ErrCodeInvalidObjectName   = "INVALID_OBJECT_NAME"
	ErrCodeUploadFailed        = "UPLOAD_FAILED"
	ErrCodeDownloadFailed      = "DOWNLOAD_FAILED"
	ErrCodeDeleteFailed        = "DELETE_FAILED"
	ErrCodeCopyFailed          = "COPY_FAILED"
	ErrCodeMoveFailed          = "MOVE_FAILED"
	ErrCodeInvalidRange        = "INVALID_RANGE"
	ErrCodeFileTooLarge        = "FILE_TOO_LARGE"
	ErrCodeInvalidFileType     = "INVALID_FILE_TYPE"
	ErrCodeInvalidPath         = "INVALID_PATH"
	ErrCodeAccessDenied        = "ACCESS_DENIED"
	ErrCodeTimeout             = "TIMEOUT"
	ErrCodeInvalidCredentials  = "INVALID_CREDENTIALS"
	ErrCodeConnectionFailed    = "CONNECTION_FAILED"
	ErrCodePresignFailed       = "PRESIGN_FAILED"
)
