package wallet

import (
	"context"
	"hyapp/pkg/appcode"
	"hyapp/pkg/xerr"
	"hyapp/services/wallet-service/internal/domain/ledger"
	"strings"
)

// GetBalances 返回用户多资产余额；鉴权范围由 gateway 或后台入口控制。
func (s *Service) GetBalances(ctx context.Context, userID int64, assetTypes []string) ([]ledger.AssetBalance, error) {
	if userID <= 0 {
		return nil, xerr.New(xerr.InvalidArgument, "user_id is required")
	}
	if s.repository == nil {
		return nil, xerr.New(xerr.Unavailable, "wallet repository is not configured")
	}
	ctx = appcode.WithContext(ctx, appcode.FromContext(ctx))
	normalized := make([]string, 0, len(assetTypes))
	for _, assetType := range assetTypes {
		assetType = strings.ToUpper(strings.TrimSpace(assetType))
		if assetType == "" {
			continue
		}
		if !ledger.ValidAssetType(assetType) {
			return nil, xerr.New(xerr.InvalidArgument, "asset_type is invalid")
		}
		normalized = append(normalized, assetType)
	}

	return s.repository.GetBalances(ctx, userID, normalized)
}

// GetWalletOverview 返回钱包首页摘要，余额和能力开关都由 wallet-service 统一给出。
func (s *Service) GetWalletOverview(ctx context.Context, userID int64) (ledger.WalletOverview, error) {
	if userID <= 0 {
		return ledger.WalletOverview{}, xerr.New(xerr.InvalidArgument, "user_id is required")
	}
	if s.repository == nil {
		return ledger.WalletOverview{}, xerr.New(xerr.Unavailable, "wallet repository is not configured")
	}
	ctx = appcode.WithContext(ctx, appcode.FromContext(ctx))
	return s.repository.GetWalletOverview(ctx, userID)
}

// GetWalletValueSummary 返回我的页钱包卡片摘要，只读取 COIN 账户。
func (s *Service) GetWalletValueSummary(ctx context.Context, userID int64) (ledger.WalletValueSummary, error) {
	if userID <= 0 {
		return ledger.WalletValueSummary{}, xerr.New(xerr.InvalidArgument, "user_id is required")
	}
	if s.repository == nil {
		return ledger.WalletValueSummary{}, xerr.New(xerr.Unavailable, "wallet repository is not configured")
	}
	ctx = appcode.WithContext(ctx, appcode.FromContext(ctx))
	return s.repository.GetWalletValueSummary(ctx, userID)
}

// GetUserGiftWall 返回用户收礼聚合投影；收礼事实只来自成功送礼账务，不读取房间运行态。
func (s *Service) GetUserGiftWall(ctx context.Context, userID int64) (ledger.UserGiftWall, error) {
	if userID <= 0 {
		return ledger.UserGiftWall{}, xerr.New(xerr.InvalidArgument, "user_id is required")
	}
	if s.repository == nil {
		return ledger.UserGiftWall{}, xerr.New(xerr.Unavailable, "wallet repository is not configured")
	}
	ctx = appcode.WithContext(ctx, appcode.FromContext(ctx))
	return s.repository.GetUserGiftWall(ctx, userID)
}

// GetDiamondExchangeConfig 返回当前 App 支持的钻石兑换规则。
func (s *Service) GetDiamondExchangeConfig(ctx context.Context, userID int64) ([]ledger.DiamondExchangeRule, error) {
	if userID <= 0 {
		return nil, xerr.New(xerr.InvalidArgument, "user_id is required")
	}
	if s.repository == nil {
		return nil, xerr.New(xerr.Unavailable, "wallet repository is not configured")
	}
	ctx = appcode.WithContext(ctx, appcode.FromContext(ctx))
	return s.repository.GetDiamondExchangeConfig(ctx, userID)
}

// ListWalletTransactions 返回当前用户钱包流水，避免我的页首屏扫描流水表。
func (s *Service) ListWalletTransactions(ctx context.Context, query ledger.ListWalletTransactionsQuery) ([]ledger.WalletTransaction, int64, error) {
	if err := validateTransactionQuery(query); err != nil {
		return nil, 0, err
	}
	query.AssetType = strings.ToUpper(strings.TrimSpace(query.AssetType))
	if query.AssetType != "" && !ledger.ValidAssetType(query.AssetType) {
		return nil, 0, xerr.New(xerr.InvalidArgument, "asset_type is invalid")
	}
	if s.repository == nil {
		return nil, 0, xerr.New(xerr.Unavailable, "wallet repository is not configured")
	}
	query.AppCode = appcode.Normalize(query.AppCode)
	ctx = appcode.WithContext(ctx, query.AppCode)
	return s.repository.ListWalletTransactions(ctx, query)
}

// ListHostPeriodDiamondTransactions 返回主播收到礼物形成的周期钻石明细；它与可消费钱包分录分开，避免恢复已废弃的 DIAMOND 钱包资产。
func (s *Service) ListHostPeriodDiamondTransactions(ctx context.Context, query ledger.ListWalletTransactionsQuery) ([]ledger.WalletTransaction, int64, error) {
	if err := validateTransactionQuery(query); err != nil {
		return nil, 0, err
	}
	if s.repository == nil {
		return nil, 0, xerr.New(xerr.Unavailable, "wallet repository is not configured")
	}
	query.AppCode = appcode.Normalize(query.AppCode)
	ctx = appcode.WithContext(ctx, query.AppCode)
	return s.repository.ListHostPeriodDiamondTransactions(ctx, query)
}

func validateTransactionQuery(query ledger.ListWalletTransactionsQuery) error {
	if query.UserID <= 0 {
		return xerr.New(xerr.InvalidArgument, "user_id is required")
	}
	// 只接受完整半开区间；单边范围会让调用方以为按日过滤成功，实际返回跨日流水。
	if query.StartAtMS < 0 || query.EndAtMS < 0 || (query.StartAtMS == 0) != (query.EndAtMS == 0) || (query.StartAtMS > 0 && query.EndAtMS <= query.StartAtMS) {
		return xerr.New(xerr.InvalidArgument, "transaction time range is invalid")
	}
	return nil
}
