package domain

import "strconv"

type ErrorType uint8

const (
	ErrorTypeUnknown ErrorType = iota
	ErrorTypeNotFound
	ErrorTypeIncorrectInput
)

func (e ErrorType) String() string {
	switch e {
	case ErrorTypeNotFound:
		return "not found"
	case ErrorTypeIncorrectInput:
		return "incorrect input"
	case ErrorTypeUnknown:
		fallthrough
	default:
		return "unknown error"
	}
}

type Error interface {
	error
	Type() ErrorType
	Code() string
}

type ErrorWithParams interface {
	Error
	Params() map[string]any
}

type ErrorPathSegment struct {
	Model string
	Field string
	Index int // Index may be <0 and this means that it is unset
}

func (s ErrorPathSegment) String() string {
	path := s.Model

	if s.Field != "" {
		if len(path) > 0 {
			path += "."
		}
		path += s.Field
		if s.Index >= 0 {
			path += "[" + strconv.Itoa(s.Index) + "]"
		}
	}

	return path
}

type ErrorWithPath interface {
	Error
	Path() ErrorPathSegment
}

type simpleError struct {
	msg  string
	typ  ErrorType
	code string
}

var _ Error = simpleError{}

func (e simpleError) Error() string {
	return e.msg
}

func (e simpleError) Type() ErrorType {
	return e.typ
}

func (e simpleError) Code() string {
	return e.code
}
