package resource

import (
	"strings"
	"unicode/utf8"

	"hyapp/services/wallet-service/internal/domain/ledger"
)

const (
	TypeAvatarFrame      = "avatar_frame"
	TypeProfileCard      = "profile_card"
	TypeCoin             = "coin"
	TypeVehicle          = "vehicle"
	TypeChatBubble       = "chat_bubble"
	TypeBadge            = "badge"
	TypeFloatingScreen   = "floating_screen"
	TypeGift             = "gift"
	TypeMicSeatIcon      = "mic_seat_icon"
	TypeMicSeatAnimation = "mic_seat_animation"
	TypeEmojiPack        = "emoji_pack"

	StatusActive   = "active"
	StatusDisabled = "disabled"

	GrantStrategyWalletCredit     = "wallet_credit"
	GrantStrategyNewEntitlement   = "new_entitlement"
	GrantStrategyExtendExpiry     = "extend_expiry"
	GrantStrategyIncreaseQuantity = "increase_quantity"
	GrantStrategySetActiveFlag    = "set_active_flag"

	GrantSubjectResource = "resource"
	GrantSubjectGroup    = "resource_group"

	GrantSourceAdmin         = "admin"
	GrantSourceManagerCenter = "manager_center"
	GrantSourceGrowthLevel   = "growth_level"
	GrantSourceAchievement   = "achievement"
	GrantSourceResourceShop  = "resource_shop"
	GrantStatusDone          = "succeeded"
	ResultWalletCredit       = "wallet_credit"
	ResultEntitlement        = "entitlement"

	GroupItemTypeResource    = "resource"
	GroupItemTypeWalletAsset = "wallet_asset"

	GiftTypeNormal     = "normal"
	GiftTypeCP         = "cp"
	GiftTypeLucky      = "lucky"
	GiftTypeSuperLucky = "super_lucky"
	GiftTypeExclusive  = "exclusive"
	GiftTypeNoble      = "noble"
	GiftTypeFlag       = "flag"
	GiftTypeActivity   = "activity"
	GiftTypeMagic      = "magic"
	GiftTypeCustom     = "custom"

	GiftTypeTabKeyNormal     = "Gift"
	GiftTypeTabKeyCP         = "CP"
	GiftTypeTabKeyLucky      = "Lucky"
	GiftTypeTabKeySuperLucky = "Super Lucky"
	GiftTypeTabKeyExclusive  = "Exclusive"
	GiftTypeTabKeyNoble      = "Noble"
	GiftTypeTabKeyFlag       = "Flag"
	GiftTypeTabKeyActivity   = "Activity"
	GiftTypeTabKeyMagic      = "Magic"
	GiftTypeTabKeyCustom     = "Custom"

	GiftEffectAnimation       = "animation"
	GiftEffectMusic           = "music"
	GiftEffectGlobalBroadcast = "global_broadcast"

	PriceTypeCoin = "coin"
	PriceTypeFree = "free"

	ShopDurationOneDay    int32 = 1
	ShopDurationThreeDays int32 = 3
	ShopDurationSevenDays int32 = 7
)

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 ResourceGroupItem struct {
	GroupItemID       int64
	GroupID           int64
	ItemType          string
	ResourceID        int64
	Resource          Resource
	WalletAssetType   string
	WalletAssetAmount int64
	Quantity          int64
	DurationMS        int64
	SortOrder         int32
	CreatedAtMS       int64
	UpdatedAtMS       int64
}

type ResourceGroup struct {
	AppCode         string
	GroupID         int64
	GroupCode       string
	Name            string
	Status          string
	Description     string
	SortOrder       int32
	Items           []ResourceGroupItem
	CreatedByUserID int64
	UpdatedByUserID int64
	CreatedAtMS     int64
	UpdatedAtMS     int64
}

type GiftConfig struct {
	AppCode          string
	GiftID           string
	ResourceID       int64
	Resource         Resource
	Status           string
	Name             string
	SortOrder        int32
	PresentationJSON string
	PriceVersion     string
	CoinPrice        int64
	// GiftPointAmount 是历史字段；送礼结算不再读取，新配置固定为 0。
	GiftPointAmount int64
	HeatValue       int64
	GiftTypeCode    string
	// CPRelationType 只在 gift_type_code=cp 的礼物上使用，值为 cp、brother 或 sister。
	CPRelationType  string
	ChargeAssetType string
	EffectiveFromMS int64
	EffectiveToMS   int64
	EffectTypes     []string
	CreatedByUserID int64
	UpdatedByUserID int64
	CreatedAtMS     int64
	UpdatedAtMS     int64
	RegionIDs       []int64
}

type GiftTypeConfig struct {
	AppCode         string
	TypeCode        string
	Name            string
	TabKey          string
	Status          string
	SortOrder       int32
	CreatedByUserID int64
	UpdatedByUserID int64
	CreatedAtMS     int64
	UpdatedAtMS     int64
}

type ResourceShopItem struct {
	AppCode         string
	ShopItemID      int64
	ResourceID      int64
	Resource        Resource
	Status          string
	DurationDays    int32
	PriceType       string
	CoinPrice       int64
	EffectiveFromMS int64
	EffectiveToMS   int64
	SortOrder       int32
	CreatedByUserID int64
	UpdatedByUserID int64
	CreatedAtMS     int64
	UpdatedAtMS     int64
}

type UserResourceEntitlement struct {
	AppCode           string
	EntitlementID     string
	UserID            int64
	ResourceID        int64
	Resource          Resource
	Status            string
	Quantity          int64
	RemainingQuantity int64
	EffectiveAtMS     int64
	ExpiresAtMS       int64
	SourceGrantID     string
	CreatedAtMS       int64
	UpdatedAtMS       int64
	Equipped          bool
}

type ResourceGrantItem struct {
	GrantItemID          int64
	GrantID              string
	ResourceID           int64
	ResourceSnapshotJSON string
	Quantity             int64
	DurationMS           int64
	ResultType           string
	WalletTransactionID  string
	EntitlementID        string
	CreatedAtMS          int64
}

type ResourceGrant struct {
	AppCode          string
	GrantID          string
	CommandID        string
	TargetUserID     int64
	GrantSource      string
	GrantSubjectType string
	GrantSubjectID   string
	Status           string
	Reason           string
	OperatorUserID   int64
	Items            []ResourceGrantItem
	CreatedAtMS      int64
	UpdatedAtMS      int64
}

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 ResourceGroupItemInput struct {
	ItemType          string
	ResourceID        int64
	WalletAssetType   string
	WalletAssetAmount int64
	Quantity          int64
	DurationMS        int64
	SortOrder         int32
}

type ListResourceGroupsQuery struct {
	AppCode    string
	Status     string
	Keyword    string
	Page       int32
	PageSize   int32
	ActiveOnly bool
}

type ResourceGroupCommand struct {
	AppCode        string
	GroupID        int64
	GroupCode      string
	Name           string
	Status         string
	Description    string
	SortOrder      int32
	Items          []ResourceGroupItemInput
	OperatorUserID int64
}

type ListGiftConfigsQuery struct {
	AppCode      string
	Status       string
	Keyword      string
	GiftTypeCode string
	Page         int32
	PageSize     int32
	ActiveOnly   bool
	RegionID     int64
	FilterRegion bool
}

type ListGiftTypeConfigsQuery struct {
	AppCode    string
	Status     string
	ActiveOnly bool
}

type GiftConfigCommand struct {
	AppCode          string
	GiftID           string
	ResourceID       int64
	Status           string
	Name             string
	SortOrder        int32
	PresentationJSON string
	PriceVersion     string
	CoinPrice        int64
	// GiftPointAmount 是历史字段；保存礼物价格时固定为 0，业务计算只读 CoinPrice。
	GiftPointAmount int64
	HeatValue       int64
	EffectiveAtMS   int64
	GiftTypeCode    string
	// CPRelationType 会写入 presentation_json，避免新增 gift_configs 表字段。
	CPRelationType  string
	ChargeAssetType string
	EffectiveFromMS int64
	EffectiveToMS   int64
	EffectTypes     []string
	OperatorUserID  int64
	RegionIDs       []int64
}

type GiftTypeConfigCommand struct {
	AppCode        string
	TypeCode       string
	Name           string
	TabKey         string
	Status         string
	SortOrder      int32
	OperatorUserID int64
}

type GrantResourceCommand struct {
	AppCode        string
	CommandID      string
	TargetUserID   int64
	ResourceID     int64
	Quantity       int64
	DurationMS     int64
	Reason         string
	OperatorUserID int64
	GrantSource    string
}

type GrantResourceGroupCommand struct {
	AppCode        string
	CommandID      string
	TargetUserID   int64
	GroupID        int64
	Reason         string
	OperatorUserID int64
	GrantSource    string
}

type ListUserResourcesQuery struct {
	AppCode      string
	UserID       int64
	ResourceType string
	ActiveOnly   bool
}

type EquipUserResourceCommand struct {
	AppCode       string
	UserID        int64
	ResourceID    int64
	EntitlementID string
}

type UnequipUserResourceCommand struct {
	AppCode      string
	UserID       int64
	ResourceType string
}

type UnequipUserResourceResult struct {
	ResourceType string
	Unequipped   bool
	UpdatedAtMS  int64
}

type BatchGetUserEquippedResourcesQuery struct {
	AppCode       string
	UserIDs       []int64
	ResourceTypes []string
}

type UserEquippedResources struct {
	UserID    int64
	Resources []UserResourceEntitlement
}

type ListResourceGrantsQuery struct {
	AppCode      string
	TargetUserID int64
	Status       string
	Page         int32
	PageSize     int32
}

type ResourceShopItemInput struct {
	ShopItemID      int64
	ResourceID      int64
	Status          string
	DurationDays    int32
	EffectiveFromMS int64
	EffectiveToMS   int64
	SortOrder       int32
}

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

type ResourceShopItemsCommand struct {
	AppCode        string
	Items          []ResourceShopItemInput
	OperatorUserID int64
}

type ResourceShopItemStatusCommand struct {
	AppCode        string
	ShopItemID     int64
	Status         string
	OperatorUserID int64
}

type ResourceShopPurchaseCommand struct {
	AppCode    string
	CommandID  string
	UserID     int64
	ShopItemID int64
}

type ResourceShopPurchaseReceipt struct {
	OrderID       string
	TransactionID string
	ShopItem      ResourceShopItem
	Resource      UserResourceEntitlement
	Balance       ledger.AssetBalance
	CoinSpent     int64
	GrantID       string
}

// BadgeGrantOutbox is a wallet resource grant event relayed to activity-service badge display projection.
type BadgeGrantOutbox struct {
	AppCode       string
	EventID       string
	EventType     string
	CommandID     string
	UserID        int64
	GrantID       string
	GrantSource   string
	PayloadJSON   string
	Status        string
	AttemptCount  int32
	FailureReason string
	CreatedAtMS   int64
	UpdatedAtMS   int64
	Items         []BadgeGrantItem
}

// BadgeGrantItem is the badge subset of a resource grant item.
type BadgeGrantItem struct {
	ResourceID           int64  `json:"resource_id"`
	ResourceCode         string `json:"resource_code"`
	ResourceType         string `json:"resource_type"`
	Name                 string `json:"name"`
	EntitlementID        string `json:"entitlement_id"`
	ResourceSnapshotJSON string `json:"resource_snapshot_json"`
	MetadataJSON         string `json:"metadata_json"`
}

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, TypeMicSeatIcon, TypeMicSeatAnimation, TypeEmojiPack:
		return true
	default:
		return false
	}
}

func ResourceTypeSellableInShop(value string) bool {
	switch NormalizeResourceType(value) {
	case TypeAvatarFrame, TypeProfileCard, TypeVehicle, TypeChatBubble, TypeBadge, TypeMicSeatIcon, TypeMicSeatAnimation:
		return true
	default:
		return false
	}
}

func ValidShopDurationDays(value int32) bool {
	switch value {
	case ShopDurationOneDay, ShopDurationThreeDays, ShopDurationSevenDays:
		return true
	default:
		return false
	}
}

func ValidStatus(value string) bool {
	switch NormalizeStatus(value) {
	case StatusActive, StatusDisabled:
		return true
	default:
		return false
	}
}

func ValidGrantStrategy(value string) bool {
	switch strings.ToLower(strings.TrimSpace(value)) {
	case GrantStrategyWalletCredit, GrantStrategyNewEntitlement, GrantStrategyExtendExpiry, GrantStrategyIncreaseQuantity, GrantStrategySetActiveFlag:
		return true
	default:
		return false
	}
}

func NormalizeGroupItemType(value string) string {
	value = strings.ToLower(strings.TrimSpace(value))
	if value == "" {
		return GroupItemTypeResource
	}
	return value
}

func ValidGroupItemType(value string) bool {
	switch NormalizeGroupItemType(value) {
	case GroupItemTypeResource, GroupItemTypeWalletAsset:
		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 NormalizePriceType(value string) string {
	return strings.ToLower(strings.TrimSpace(value))
}

func ValidPriceType(value string) bool {
	switch NormalizePriceType(value) {
	case PriceTypeCoin, PriceTypeFree:
		return true
	default:
		return false
	}
}

func NormalizeGiftTypeCode(value string) string {
	value = strings.ToLower(strings.TrimSpace(value))
	value = strings.ReplaceAll(value, "-", "_")
	if value == "" {
		return GiftTypeNormal
	}
	return value
}

func ValidGiftTypeCode(value string) bool {
	value = NormalizeGiftTypeCode(value)
	if value == "" || len(value) > 32 {
		return false
	}
	for index, char := range value {
		if index == 0 && (char < 'a' || char > 'z') {
			return false
		}
		if (char >= 'a' && char <= 'z') || (char >= '0' && char <= '9') || char == '_' {
			continue
		}
		return false
	}
	return true
}

func NormalizeGiftTypeTabKey(value string) string {
	return strings.TrimSpace(value)
}

func ValidGiftTypeTabKey(value string) bool {
	value = NormalizeGiftTypeTabKey(value)
	return value != "" && utf8.RuneCountInString(value) <= 32
}

func DefaultGiftTypeConfigs(appCode string) []GiftTypeConfig {
	appCode = strings.TrimSpace(appCode)
	defaults := []GiftTypeConfig{
		{TypeCode: GiftTypeNormal, Name: "普通礼物", TabKey: GiftTypeTabKeyNormal, Status: StatusActive, SortOrder: 10},
		{TypeCode: GiftTypeCP, Name: "CP礼物", TabKey: GiftTypeTabKeyCP, Status: StatusActive, SortOrder: 20},
		{TypeCode: GiftTypeLucky, Name: "幸运礼物", TabKey: GiftTypeTabKeyLucky, Status: StatusActive, SortOrder: 30},
		{TypeCode: GiftTypeSuperLucky, Name: "超级幸运礼物", TabKey: GiftTypeTabKeySuperLucky, Status: StatusActive, SortOrder: 40},
		{TypeCode: GiftTypeExclusive, Name: "专属礼物", TabKey: GiftTypeTabKeyExclusive, Status: StatusActive, SortOrder: 50},
		{TypeCode: GiftTypeNoble, Name: "贵族礼物", TabKey: GiftTypeTabKeyNoble, Status: StatusActive, SortOrder: 60},
		{TypeCode: GiftTypeFlag, Name: "国旗礼物", TabKey: GiftTypeTabKeyFlag, Status: StatusActive, SortOrder: 70},
		{TypeCode: GiftTypeActivity, Name: "活动礼物", TabKey: GiftTypeTabKeyActivity, Status: StatusActive, SortOrder: 80},
		{TypeCode: GiftTypeMagic, Name: "魔法礼物", TabKey: GiftTypeTabKeyMagic, Status: StatusActive, SortOrder: 90},
		{TypeCode: GiftTypeCustom, Name: "定制礼物", TabKey: GiftTypeTabKeyCustom, Status: StatusActive, SortOrder: 100},
	}
	for index := range defaults {
		defaults[index].AppCode = appCode
	}
	return defaults
}

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

func ValidGiftEffectType(value string) bool {
	switch NormalizeGiftEffectType(value) {
	case GiftEffectAnimation, GiftEffectMusic, GiftEffectGlobalBroadcast:
		return true
	default:
		return false
	}
}

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
}
