package grpc

import (
	walletv1 "hyapp.local/api/proto/wallet/v1"
	"hyapp/pkg/appcode"
	resourcedomain "hyapp/services/wallet-service/internal/domain/resource"
)

func resourceToProto(resource resourcedomain.Resource) *walletv1.Resource {
	return &walletv1.Resource{
		AppCode:             appcode.Normalize(resource.AppCode),
		ResourceId:          resource.ResourceID,
		ResourceCode:        resource.ResourceCode,
		ResourceType:        resource.ResourceType,
		Name:                resource.Name,
		Status:              resource.Status,
		Grantable:           resource.Grantable,
		GrantStrategy:       resource.GrantStrategy,
		WalletAssetType:     resource.WalletAssetType,
		WalletAssetAmount:   resource.WalletAssetAmount,
		PriceType:           resource.PriceType,
		CoinPrice:           resource.CoinPrice,
		GiftPointAmount:     0,
		UsageScopes:         resource.UsageScopes,
		AssetUrl:            resource.AssetURL,
		PreviewUrl:          resource.PreviewURL,
		AnimationUrl:        resource.AnimationURL,
		MetadataJson:        resource.MetadataJSON,
		SortOrder:           resource.SortOrder,
		CreatedByUserId:     resource.CreatedByUserID,
		UpdatedByUserId:     resource.UpdatedByUserID,
		CreatedAtMs:         resource.CreatedAtMS,
		UpdatedAtMs:         resource.UpdatedAtMS,
		ManagerGrantEnabled: resource.ManagerGrantEnabled,
	}
}

func resourceShopItemToProto(item resourcedomain.ResourceShopItem) *walletv1.ResourceShopItem {
	return &walletv1.ResourceShopItem{
		AppCode:         appcode.Normalize(item.AppCode),
		ShopItemId:      item.ShopItemID,
		ResourceId:      item.ResourceID,
		Resource:        resourceToProto(item.Resource),
		Status:          item.Status,
		DurationDays:    item.DurationDays,
		PriceType:       item.PriceType,
		CoinPrice:       item.CoinPrice,
		EffectiveFromMs: item.EffectiveFromMS,
		EffectiveToMs:   item.EffectiveToMS,
		SortOrder:       item.SortOrder,
		CreatedByUserId: item.CreatedByUserID,
		UpdatedByUserId: item.UpdatedByUserID,
		CreatedAtMs:     item.CreatedAtMS,
		UpdatedAtMs:     item.UpdatedAtMS,
	}
}

func resourceShopPurchaseOrderToProto(item resourcedomain.ResourceShopPurchaseOrder) *walletv1.ResourceShopPurchaseOrder {
	return &walletv1.ResourceShopPurchaseOrder{
		AppCode:             appcode.Normalize(item.AppCode),
		OrderId:             item.OrderID,
		CommandId:           item.CommandID,
		UserId:              item.UserID,
		ShopItemId:          item.ShopItemID,
		ResourceId:          item.ResourceID,
		Resource:            resourceToProto(item.Resource),
		DurationDays:        item.DurationDays,
		PriceCoin:           item.PriceCoin,
		Status:              item.Status,
		WalletTransactionId: item.WalletTransactionID,
		ResourceGrantId:     item.ResourceGrantID,
		EntitlementId:       item.EntitlementID,
		CreatedAtMs:         item.CreatedAtMS,
		UpdatedAtMs:         item.UpdatedAtMS,
	}
}

func resourceShopPurchaseReceiptToProto(receipt resourcedomain.ResourceShopPurchaseReceipt) *walletv1.PurchaseResourceShopItemResponse {
	return &walletv1.PurchaseResourceShopItemResponse{
		OrderId:         receipt.OrderID,
		TransactionId:   receipt.TransactionID,
		ResourceGrantId: receipt.GrantID,
		ShopItem:        resourceShopItemToProto(receipt.ShopItem),
		Resource:        userResourceToProto(receipt.Resource),
		Balance:         balanceToProto(receipt.Balance),
		CoinSpent:       receipt.CoinSpent,
	}
}

func managerGrantEnabledOrDefault(value *bool) bool {
	if value == nil {

		return false
	}
	return *value
}

func resourceGroupToProto(group resourcedomain.ResourceGroup) *walletv1.ResourceGroup {
	items := make([]*walletv1.ResourceGroupItem, 0, len(group.Items))
	for _, item := range group.Items {
		items = append(items, &walletv1.ResourceGroupItem{
			GroupItemId:       item.GroupItemID,
			GroupId:           item.GroupID,
			ResourceId:        item.ResourceID,
			Resource:          resourceToProto(item.Resource),
			Quantity:          item.Quantity,
			DurationMs:        item.DurationMS,
			SortOrder:         item.SortOrder,
			CreatedAtMs:       item.CreatedAtMS,
			UpdatedAtMs:       item.UpdatedAtMS,
			ItemType:          item.ItemType,
			WalletAssetType:   item.WalletAssetType,
			WalletAssetAmount: item.WalletAssetAmount,
		})
	}
	return &walletv1.ResourceGroup{
		AppCode:         appcode.Normalize(group.AppCode),
		GroupId:         group.GroupID,
		GroupCode:       group.GroupCode,
		Name:            group.Name,
		Status:          group.Status,
		Description:     group.Description,
		SortOrder:       group.SortOrder,
		Items:           items,
		CreatedByUserId: group.CreatedByUserID,
		UpdatedByUserId: group.UpdatedByUserID,
		CreatedAtMs:     group.CreatedAtMS,
		UpdatedAtMs:     group.UpdatedAtMS,
	}
}

func resourceGroupSnapshotToProto(item resourcedomain.ResourceGroupSnapshot) *walletv1.ResourceGroupSnapshot {
	return &walletv1.ResourceGroupSnapshot{
		AppCode: item.AppCode, SnapshotId: item.SnapshotID, PinKey: item.PinKey,
		SourceGroupId: item.SourceGroupID, VersionNo: item.VersionNo, SnapshotHash: item.SnapshotHash,
		Group: resourceGroupToProto(item.Group), CreatedByUserId: item.CreatedByUserID, CreatedAtMs: item.CreatedAtMS,
		SourceGroupUpdatedAtMs: item.SourceGroupUpdatedAtMS, SourceContentHash: item.SourceContentHash,
	}
}

func giftConfigToProto(gift resourcedomain.GiftConfig) *walletv1.GiftConfig {
	return &walletv1.GiftConfig{
		AppCode:          appcode.Normalize(gift.AppCode),
		GiftId:           gift.GiftID,
		ResourceId:       gift.ResourceID,
		Resource:         resourceToProto(gift.Resource),
		Status:           gift.Status,
		Name:             gift.Name,
		SortOrder:        gift.SortOrder,
		PresentationJson: gift.PresentationJSON,
		PriceVersion:     gift.PriceVersion,
		ChargeAssetType:  gift.ChargeAssetType,
		CoinPrice:        gift.CoinPrice,
		GiftPointAmount:  0,
		HeatValue:        gift.HeatValue,
		GiftTypeCode:     gift.GiftTypeCode,
		VipLevel:         gift.VIPLevel,
		CpRelationType:   gift.CPRelationType,
		EffectiveFromMs:  gift.EffectiveFromMS,
		EffectiveToMs:    gift.EffectiveToMS,
		EffectTypes:      gift.EffectTypes,
		CreatedByUserId:  gift.CreatedByUserID,
		UpdatedByUserId:  gift.UpdatedByUserID,
		CreatedAtMs:      gift.CreatedAtMS,
		UpdatedAtMs:      gift.UpdatedAtMS,
		RegionIds:        gift.RegionIDs,
	}
}

func giftTypeConfigToProto(item resourcedomain.GiftTypeConfig) *walletv1.GiftTypeConfig {
	return &walletv1.GiftTypeConfig{
		AppCode:         appcode.Normalize(item.AppCode),
		TypeCode:        item.TypeCode,
		Name:            item.Name,
		TabKey:          item.TabKey,
		Status:          item.Status,
		SortOrder:       item.SortOrder,
		CreatedByUserId: item.CreatedByUserID,
		UpdatedByUserId: item.UpdatedByUserID,
		CreatedAtMs:     item.CreatedAtMS,
		UpdatedAtMs:     item.UpdatedAtMS,
	}
}

func userResourceToProto(item resourcedomain.UserResourceEntitlement) *walletv1.UserResourceEntitlement {
	out := &walletv1.UserResourceEntitlement{
		AppCode:              appcode.Normalize(item.AppCode),
		EntitlementId:        item.EntitlementID,
		UserId:               item.UserID,
		ResourceId:           item.ResourceID,
		Resource:             resourceToProto(item.Resource),
		Status:               item.Status,
		Quantity:             item.Quantity,
		RemainingQuantity:    item.RemainingQuantity,
		EffectiveAtMs:        item.EffectiveAtMS,
		ExpiresAtMs:          item.ExpiresAtMS,
		SourceGrantId:        item.SourceGrantID,
		CreatedAtMs:          item.CreatedAtMS,
		UpdatedAtMs:          item.UpdatedAtMS,
		Equipped:             item.Equipped,
		SourceSnapshotId:     item.SourceSnapshotID,
		ResourceSnapshotHash: item.ResourceSnapshotHash,
		VipBenefitCodes:      append([]string(nil), item.VIPBenefitCodes...),
	}
	for _, gift := range item.PinnedGiftConfigs {
		out.PinnedGiftConfigs = append(out.PinnedGiftConfigs, giftConfigToProto(gift))
	}
	return out
}

func resourceGrantToProto(grant resourcedomain.ResourceGrant) *walletv1.ResourceGrant {
	items := make([]*walletv1.ResourceGrantItem, 0, len(grant.Items))
	for _, item := range grant.Items {
		items = append(items, &walletv1.ResourceGrantItem{
			GrantItemId:          item.GrantItemID,
			GrantId:              item.GrantID,
			ResourceId:           item.ResourceID,
			ResourceSnapshotJson: item.ResourceSnapshotJSON,
			Quantity:             item.Quantity,
			DurationMs:           item.DurationMS,
			ResultType:           item.ResultType,
			WalletTransactionId:  item.WalletTransactionID,
			EntitlementId:        item.EntitlementID,
			CreatedAtMs:          item.CreatedAtMS,
		})
	}
	return &walletv1.ResourceGrant{
		AppCode:          appcode.Normalize(grant.AppCode),
		GrantId:          grant.GrantID,
		CommandId:        grant.CommandID,
		TargetUserId:     grant.TargetUserID,
		GrantSource:      grant.GrantSource,
		GrantSubjectType: grant.GrantSubjectType,
		GrantSubjectId:   grant.GrantSubjectID,
		Status:           grant.Status,
		Reason:           grant.Reason,
		OperatorUserId:   grant.OperatorUserID,
		Items:            items,
		CreatedAtMs:      grant.CreatedAtMS,
		UpdatedAtMs:      grant.UpdatedAtMS,
		RevokedAtMs:      grant.RevokedAtMS,
		RevokedByUserId:  grant.RevokedByUserID,
		RevokeReason:     grant.RevokeReason,
	}
}
