package resource

import (
	"crypto/sha256"
	"encoding/hex"
	"encoding/json"
	"hyapp/services/wallet-service/internal/domain/ledger"
	"sort"
	"strings"
)

type Resource struct {
	AppCode           string
	ResourceID        int64
	ResourceCode      string
	ResourceType      string
	Name              string
	Status            string
	Grantable         bool
	GrantStrategy     string
	WalletAssetType   string
	WalletAssetAmount int64
	PriceType         string
	CoinPrice         int64
	// GiftPointAmount 是历史字段；GIFT_POINT 已下线，新资源和礼物配置只保留真实 COIN 价格。
	GiftPointAmount     int64
	UsageScopes         []string
	AssetURL            string
	PreviewURL          string
	AnimationURL        string
	MetadataJSON        string
	SortOrder           int32
	CreatedByUserID     int64
	UpdatedByUserID     int64
	CreatedAtMS         int64
	UpdatedAtMS         int64
	ManagerGrantEnabled bool
}

type ListResourcesQuery struct {
	AppCode          string
	ResourceType     string
	Status           string
	Keyword          string
	Page             int32
	PageSize         int32
	ActiveOnly       bool
	ManagerGrantOnly bool
}

type ResourceCommand struct {
	AppCode           string
	ResourceID        int64
	ResourceCode      string
	ResourceType      string
	Name              string
	Status            string
	Grantable         bool
	GrantStrategy     string
	WalletAssetType   string
	WalletAssetAmount int64
	PriceType         string
	CoinPrice         int64
	// GiftPointAmount 是历史字段；保存资源时固定为 0，保留字段只兼容旧表结构。
	GiftPointAmount     int64
	UsageScopes         []string
	AssetURL            string
	PreviewURL          string
	AnimationURL        string
	MetadataJSON        string
	SortOrder           int32
	OperatorUserID      int64
	ManagerGrantEnabled bool
}

type StatusCommand struct {
	AppCode        string
	ID             int64
	StringID       string
	Status         string
	OperatorUserID int64
}

type BatchDeleteResourcesCommand struct {
	AppCode        string
	ResourceIDs    []int64
	OperatorUserID int64
}

// CanonicalResourceJSON is the immutable entitlement projection. Usage scopes are set-like owner data,
// therefore sorting them prevents an order-only edit from creating a different grant semantic.
func CanonicalResourceJSON(resource Resource) ([]byte, error) {
	canonical := resource
	canonical.UsageScopes = append([]string(nil), resource.UsageScopes...)
	sort.Strings(canonical.UsageScopes)
	return json.Marshal(canonical)
}

func ResourceContentHash(resource Resource) (string, error) {
	body, err := CanonicalResourceJSON(resource)
	if err != nil {
		return "", err
	}
	sum := sha256.Sum256(body)
	return hex.EncodeToString(sum[:]), nil
}

func NormalizeStatus(value string) string {
	value = strings.ToLower(strings.TrimSpace(value))
	if value == "" {
		return StatusActive
	}
	return value
}

func NormalizeGrantSource(value string) string {
	value = strings.ToLower(strings.TrimSpace(value))
	if value == "" {
		return GrantSourceAdmin
	}
	return value
}

func ValidResourceType(value string) bool {
	switch strings.ToLower(strings.TrimSpace(value)) {
	case TypeAvatarFrame, TypeProfileCard, TypeCoin, TypeVehicle, TypeChatBubble, TypeBadge, TypeFloatingScreen, TypeGift, TypeGiftTraySkin, TypeMicSeatIcon, TypeMicSeatAnimation, TypeRoomBorder, TypeRoomNameStyle, TypeEmojiPack, TypeVIPTrialCard:
		return true
	default:
		return false
	}
}

func NormalizeResourceType(value string) string {
	return strings.ToLower(strings.TrimSpace(value))
}

func NormalizeGrantStrategy(value string) string {
	return strings.ToLower(strings.TrimSpace(value))
}

func NormalizeWalletAssetType(value string) string {
	return strings.ToUpper(strings.TrimSpace(value))
}

func IsWalletCredit(resource Resource) bool {
	return NormalizeGrantStrategy(resource.GrantStrategy) == GrantStrategyWalletCredit
}

func IsCoinResource(resource Resource) bool {
	return NormalizeResourceType(resource.ResourceType) == TypeCoin
}

func WalletAssetForCoin() string {
	return ledger.AssetCoin
}
