// package arch_node -- архитектурный узел
package arch_node

import (
	"fmt"

	"github.com/google/uuid"
	"gitp78su.ipnodns.ru/svi/kern/v3"
	"gitp78su.ipnodns.ru/svi/kern/v3/krn/ktypes"

	"gitp78su.ipnodns.ru/svi/goarch/lev0/alias"
)

// ArchNode -- архитектурный узел
type ArchNode struct {
	Id_       alias.ArchId   `yaml:"id"`        // Идентификатор узла
	Type_     alias.ArchType `yaml:"type"`      // Тип узла
	ParentId_ alias.ArchId   `yaml:"parent_id"` // ID предка
}

var (
	hassert = kern.GetFnHassert()
)

// NewArchNode -- возвращает новый архитектурный узел
func NewArchNode(archType alias.ArchType, parentId alias.ArchId) *ArchNode {
	sf := &ArchNode{
		Id_:       alias.ArchId(uuid.New().String()),
		Type_:     archType,
		ParentId_: parentId,
	}
	sf.selfCheck()
	return sf
}

// ParentId -- возвращает ID родителя
//
//go:fix inline
func (sf *ArchNode) ParentId() alias.ArchId {
	return sf.ParentId_
}

// Type -- возвращает тип объекта
//
//go:fix inline
func (sf *ArchNode) Type() alias.ArchType {
	return sf.Type_
}

// Id -- возвращает ID объекта
//
//go:fix inline
func (sf *ArchNode) Id() alias.ArchId {
	return sf.Id_
}

// SelfCheck -- самопроверка базового элемента
func (sf *ArchNode) selfCheck() {
	hassert(sf.Id_ != "", "ArchNode.selfCheck(): id is empty")
	hassert(sf.Type_ != "", "ArchNode.selfCheck(): id:%s, Type_ is empty", sf.Id_)
	hassert(sf.ParentId_ != "", "ArchNode.selfCheck(): id:%s, ParentId_ is empty", sf.Id_)
}

// InvarNode -- проверка инвариантов
func (sf *ArchNode) InvarNode() ktypes.Option[error] {
	if sf.Id_ == "" {
		err := fmt.Errorf("ArchNode.InvarNode(): Id_ is empty")
		return ktypes.NewSome(err)
	}
	if sf.Type_ == "" {
		err := fmt.Errorf("ArchNode.InvarNode(): id:%s, Type_ is empty", sf.Id_)
		return ktypes.NewSome(err)
	}
	if sf.ParentId_ == "" {
		err := fmt.Errorf("ArchNode.InvarNode(): id:%s, ParentId_ is empty", sf.Id_)
		return ktypes.NewSome(err)
	}
	return ktypes.NewNone[error]()
}
