// package arch_use_case -- вариант использования
package arch_use_case

import (
	"fmt"

	// "gitp78su.ipnodns.ru/svi/kern/v3"

	"gitp78su.ipnodns.ru/svi/goarch/lev0/alias"
	"gitp78su.ipnodns.ru/svi/goarch/lev0/cons"
	"gitp78su.ipnodns.ru/svi/goarch/lev0/types"
	"gitp78su.ipnodns.ru/svi/goarch/lev1/arch_node"
	"gitp78su.ipnodns.ru/svi/goarch/lev1/arch_text"
	"gitp78su.ipnodns.ru/svi/kern/v3/krn/ktypes"
)

// ArchUseCase -- вариант использования
type ArchUseCase struct {
	*arch_node.ArchNode
	Links_  []alias.ArchId `yaml:"links_id"` // Список ссылок
	links   map[alias.ArchId]types.IArchLink
	TextId_ alias.ArchId `yaml:"text_id"` // ID текста
	text    *arch_text.ArchText
}

// var (
// 	hassert = kern.GetFnHassert()
// )

// NewUseCase -- возвращает новый вариант использования
func NewUseCase(links []alias.ArchId, parentId alias.ArchId) *ArchUseCase {
	// id := elemBase.Id()
	// _links0, isOk := elemBase.Elem_["links"]
	// hassert(isOk, "NewUseCase(): id=%q, links not found", id)
	// _links, isOk := _links0.([]interface{})
	// hassert(isOk, "NewUseCase(): id=%q, `links`(%+v) not []interface{}", id, _links0)
	// for _, _id := range _links {
	// 	id0, isOk := _id.(string)
	// 	hassert(isOk, "NewUseCase(): id=%q, `link`(%T, %+v) not string", id, _id, _id)
	// 	id1 := alias.Id(id0)
	// 	hassert(id1 != "", "NewUseCase(): id=%q, `link` is empty", id)
	// 	links = append(links, id1)
	// }
	sf := &ArchUseCase{
		ArchNode: arch_node.NewArchNode("use_case", parentId),
		Links_:   links,
	}
	sf.SelfCheck()
	_ = types.IArchUseCase(sf)
	return sf
}

// Text -- текст варианта использования
//
//go:fix inline
func (sf *ArchUseCase) Text() types.IArchText {
	return sf.text
}

// InvarCheck -- проверка собственного состояния
func (sf *ArchUseCase) InvarCheck() ktypes.Option[error] {
	optErr := sf.ArchNode.InvarNode()
	if optErr.IsVal() {
		err := fmt.Errorf("ArchUseCase.InvarCheck(): err=\n\t%w", optErr.Val())
		return ktypes.NewSome(err)
	}
	sf.SelfCheck()
	return ktypes.NewNone[error]()
}

// SelfCheck -- самопроверка
func (sf *ArchUseCase) SelfCheck() {
	sf.InvarNode()
	var msgErr string
	// Нет ссылок
	if len(sf.Links_) == 0 {
		return
	}
	// Проверить, что ссылки реально существует
	for id, link := range sf.links {
		if link.Type() != cons.TypeUseLink {
			msgErr += fmt.Sprintf("id=%q, не тип %q, тип=%q\n", id, cons.TypeUseLink, link.Type())
			continue
		}
		// Проверить что ссылка взаимная
		if !(link.SrcId() == sf.Id() || link.DstId() == sf.Id()) {
			msgErr += fmt.Sprintf("id=%q, ссылка не взаимная\nsrc=%q, dst=%q\n",
				id, link.SrcId(), link.DstId())
		}
	}
}

// Links -- ссылки вариантов использования
func (sf *ArchUseCase) Links() map[alias.ArchId]types.IArchLink {
	return sf.links
}
