package payments

import (
	"cmp"
	"slices"
)

// catalogRank is the canonical listing key for a catalog product: whether it is a chip pack, its
// value subgroup (see [valueGroup]; unused for a pack) and the minor-unit amount its section sorts by
// (a pack's direct rouble price, a value's chip price; math.MaxInt64 when absent, so a misconfigured
// row sorts last rather than leading).
type catalogRank struct {
	pack   bool
	group  int
	amount int64
}

// compareCatalogRank is the single canonical product order, shared by the storefront ([projectCatalog]),
// the public offer ([projectOfferPricing]) and the admin catalog ([SortAdminCatalog]): chip packs
// first, ascending by rouble price; then chip-priced values grouped hints → no-ads → combo →
// tournament and, within a group, ascending by chip price. A pack's group is unused (all packs share
// one section). Callers use it through [entryRank] / [adminRank], which build the key from each
// product shape, so the subgroup and ordering rules live in exactly one place.
func compareCatalogRank(a, b catalogRank) int {
	if a.pack != b.pack {
		if a.pack {
			return -1 // packs (sales) before values (chip exchange)
		}
		return 1
	}
	if !a.pack {
		if d := cmp.Compare(a.group, b.group); d != 0 {
			return d
		}
	}
	return cmp.Compare(a.amount, b.amount)
}

// entryRank builds the canonical rank of a storefront / offer catalog entry.
func entryRank(e catalogEntry) catalogRank {
	if isPackEntry(e) {
		return catalogRank{pack: true, amount: offerSortAmount(e, string(SourceDirect), CurrencyRUB)}
	}
	return catalogRank{group: offerValueGroup(e), amount: offerSortAmount(e, "", CurrencyChip)}
}

// adminRank builds the canonical rank of an admin catalog product.
func adminRank(p AdminProduct) catalogRank {
	if adminIsPack(p) {
		return catalogRank{pack: true, amount: adminPriceAmount(p, string(SourceDirect), CurrencyRUB)}
	}
	return catalogRank{group: adminValueGroup(p), amount: adminPriceAmount(p, "", CurrencyChip)}
}

// sortCatalogEntries orders storefront / offer entries in place into the canonical listing order
// ([compareCatalogRank]). Stable, so equal-keyed products keep their incoming (creation) order.
func sortCatalogEntries(entries []catalogEntry) {
	slices.SortStableFunc(entries, func(a, b catalogEntry) int {
		return compareCatalogRank(entryRank(a), entryRank(b))
	})
}
