package deliberi

import (
	"context"

	"github.com/yuin/goldmark"
	"github.com/yuin/goldmark/ast"
	"github.com/yuin/goldmark/text"

	markupext "tangled.org/core/deliberi/markup"
)

var mentionParser = goldmark.New(goldmark.WithExtensions(markupext.AtExt))

func extractMentionHandles(body string) []string {
	if body == "" {
		return nil
	}

	doc := mentionParser.Parser().Parse(text.NewReader([]byte(body)))

	var handles []string
	seen := make(map[string]struct{})
	_ = ast.Walk(doc, func(n ast.Node, entering bool) (ast.WalkStatus, error) {
		if !entering || n.Kind() != markupext.KindAt {
			return ast.WalkContinue, nil
		}
		handle := n.(*markupext.AtNode).Handle
		if _, ok := seen[handle]; ok {
			return ast.WalkContinue, nil
		}
		seen[handle] = struct{}{}
		handles = append(handles, handle)
		return ast.WalkContinue, nil
	})
	return handles
}

// mentionDids resolves the @handles in body to DIDs, dropping the author and
// any handle that fails to resolve.
func (i *Ingester) mentionDids(ctx context.Context, authorDid, body string) []string {
	handles := extractMentionHandles(body)
	if len(handles) == 0 {
		return nil
	}

	var dids []string
	for _, handle := range handles {
		id, err := i.idResolver.ResolveIdent(ctx, handle)
		if err != nil {
			i.logger.Warn("resolving mention", "err", err, "handle", handle)
			continue
		}
		did := id.DID.String()
		if did == authorDid {
			continue
		}
		dids = append(dids, did)
	}
	return dids
}
