package itemregistry

import (
	"sort"

	"gitea.maximumdirect.net/eric/notarius/internal/core/source"
	"gitea.maximumdirect.net/eric/notarius/internal/modules/dnd"
	"gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/items/identity"
	"gitea.maximumdirect.net/eric/notarius/internal/modules/dnd/shared"
)

type orderedItemResponse struct {
	value       itemResponse
	earliest    int
	hasEvidence bool
}

func canonicalizeResponse(response *extractionResponse, order shared.SourceRefOrder, sourceID string) {
	if response == nil {
		return
	}
	ordered := make([]orderedItemResponse, len(response.Items))
	for index := range response.Items {
		earliest, hasEvidence := canonicalizeItem(&response.Items[index], order, sourceID)
		ordered[index] = orderedItemResponse{value: response.Items[index], earliest: earliest, hasEvidence: hasEvidence}
	}
	sort.SliceStable(ordered, func(left, right int) bool {
		if ordered[left].hasEvidence != ordered[right].hasEvidence {
			return ordered[left].hasEvidence
		}
		if !ordered[left].hasEvidence {
			return false
		}
		return ordered[left].earliest < ordered[right].earliest
	})
	for index := range ordered {
		response.Items[index] = ordered[index].value
	}
}

func canonicalizeItem(item *itemResponse, order shared.SourceRefOrder, sourceID string) (int, bool) {
	if item == nil {
		return 0, false
	}
	item.Name = identity.NormalizeDisplay(item.Name)
	refs := order.Canonicalize(order.OrderEndpoints(canonicalSourceRefs(item.SourceRefs, sourceID)))
	item.SourceRefs = itemResponseRefs(refs)
	return order.EarliestValid(refs)
}

func canonicalItemRegistry(response extractionResponse, sourceID string) dnd.ItemRegistry {
	if response.Items == nil {
		return dnd.ItemRegistry{Items: nil}
	}
	items := make([]dnd.Item, len(response.Items))
	for index, item := range response.Items {
		refs := canonicalSourceRefs(item.SourceRefs, sourceID)
		items[index] = dnd.Item{
			ID:         identity.DeriveID(item.Name),
			Name:       item.Name,
			SourceRefs: refs,
		}
	}
	return dnd.ItemRegistry{Items: items}
}

func canonicalSourceRefs(values []itemSourceRefResponse, sourceID string) []source.SourceRef {
	if values == nil {
		return nil
	}
	refs := make([]source.SourceRef, len(values))
	for index, value := range values {
		refs[index] = source.SourceRef{SourceID: sourceID, StartUnitID: value.StartUnitID, EndUnitID: value.EndUnitID}
	}
	return refs
}

func itemResponseRefs(values []source.SourceRef) []itemSourceRefResponse {
	if values == nil {
		return nil
	}
	refs := make([]itemSourceRefResponse, len(values))
	for index, value := range values {
		refs[index] = itemSourceRefResponse{StartUnitID: value.StartUnitID, EndUnitID: value.EndUnitID}
	}
	return refs
}
