package grpc

import (
	"context"

	walletv1 "hyapp.local/api/proto/wallet/v1"
	"hyapp/pkg/appcode"
	"hyapp/pkg/xerr"
	"hyapp/services/wallet-service/internal/domain/ledger"
)

// AdminCreditCoinSellerStock 处理后台币商进货或金币补偿，币商身份由 admin-server 先行校验。
func (s *Server) AdminCreditCoinSellerStock(ctx context.Context, req *walletv1.AdminCreditCoinSellerStockRequest) (*walletv1.AdminCreditCoinSellerStockResponse, error) {
	ctx = appcode.WithContext(ctx, req.GetAppCode())
	receipt, err := s.svc.AdminCreditCoinSellerStock(ctx, ledger.CoinSellerStockCreditCommand{
		AppCode:          req.GetAppCode(),
		CommandID:        req.GetCommandId(),
		SellerUserID:     req.GetSellerUserId(),
		SellerCountryID:  req.GetSellerCountryId(),
		SellerRegionID:   req.GetSellerRegionId(),
		StockType:        req.GetStockType(),
		CoinAmount:       req.GetCoinAmount(),
		PaidCurrencyCode: req.GetPaidCurrencyCode(),
		PaidAmountMicro:  req.GetPaidAmountMicro(),
		PaymentRef:       req.GetPaymentRef(),
		EvidenceRef:      req.GetEvidenceRef(),
		OperatorUserID:   req.GetOperatorUserId(),
		Reason:           req.GetReason(),
	})
	if err != nil {
		return nil, xerr.ToGRPCError(err)
	}

	return &walletv1.AdminCreditCoinSellerStockResponse{
		TransactionId:          receipt.TransactionID,
		SellerUserId:           receipt.SellerUserID,
		StockType:              receipt.StockType,
		CoinAmount:             receipt.CoinAmount,
		PaidCurrencyCode:       receipt.PaidCurrencyCode,
		PaidAmountMicro:        receipt.PaidAmountMicro,
		CountsAsSellerRecharge: receipt.CountsAsSellerRecharge,
		BalanceAfter:           receipt.BalanceAfter,
		CreatedAtMs:            receipt.CreatedAtMS,
	}, nil
}

// TransferCoinFromSeller 处理币商转玩家金币，调用方必须先完成币商身份校验。
func (s *Server) TransferCoinFromSeller(ctx context.Context, req *walletv1.TransferCoinFromSellerRequest) (*walletv1.TransferCoinFromSellerResponse, error) {
	ctx = appcode.WithContext(ctx, req.GetAppCode())
	receipt, err := s.svc.TransferCoinFromSeller(ctx, ledger.CoinSellerTransferCommand{
		AppCode:         req.GetAppCode(),
		CommandID:       req.GetCommandId(),
		SellerUserID:    req.GetSellerUserId(),
		TargetUserID:    req.GetTargetUserId(),
		TargetCountryID: req.GetTargetCountryId(),
		SellerRegionID:  req.GetSellerRegionId(),
		TargetRegionID:  req.GetTargetRegionId(),
		Amount:          req.GetAmount(),
		Reason:          req.GetReason(),
	})
	if err != nil {
		return nil, xerr.ToGRPCError(err)
	}

	return &walletv1.TransferCoinFromSellerResponse{
		TransactionId:                receipt.TransactionID,
		SellerBalanceAfter:           receipt.SellerBalanceAfter,
		TargetBalanceAfter:           receipt.TargetBalanceAfter,
		Amount:                       receipt.Amount,
		RechargeUsdMinor:             receipt.RechargeUSDMinor,
		RechargeCurrencyCode:         receipt.RechargeCurrencyCode,
		RechargePolicyId:             receipt.RechargePolicyID,
		RechargePolicyVersion:        receipt.RechargePolicyVersion,
		RechargePolicyCoinAmount:     receipt.RechargePolicyCoinAmount,
		RechargePolicyUsdMinorAmount: receipt.RechargePolicyUSDMinorUnit,
	}, nil
}

// TransferCoinSellerStockToChild 处理父币商转直属子币商专用金币库存，调用方必须先完成父子关系校验。
func (s *Server) TransferCoinSellerStockToChild(ctx context.Context, req *walletv1.TransferCoinSellerStockToChildRequest) (*walletv1.TransferCoinSellerStockToChildResponse, error) {
	ctx = appcode.WithContext(ctx, req.GetAppCode())
	receipt, err := s.svc.TransferCoinSellerStockToChild(ctx, ledger.CoinSellerSubTransferCommand{
		AppCode:      req.GetAppCode(),
		CommandID:    req.GetCommandId(),
		ParentUserID: req.GetParentUserId(),
		ChildUserID:  req.GetChildUserId(),
		RegionID:     req.GetRegionId(),
		Amount:       req.GetAmount(),
		Reason:       req.GetReason(),
	})
	if err != nil {
		return nil, xerr.ToGRPCError(err)
	}

	return &walletv1.TransferCoinSellerStockToChildResponse{
		TransactionId:      receipt.TransactionID,
		ParentBalanceAfter: receipt.ParentBalanceAfter,
		ChildBalanceAfter:  receipt.ChildBalanceAfter,
		Amount:             receipt.Amount,
		CreatedAtMs:        receipt.CreatedAtMS,
	}, nil
}

// ListCoinSellerSalaryExchangeRateTiers 返回工资转币商使用的区域比例区间，调用方用它做预计到账展示。
func (s *Server) ListCoinSellerSalaryExchangeRateTiers(ctx context.Context, req *walletv1.ListCoinSellerSalaryExchangeRateTiersRequest) (*walletv1.ListCoinSellerSalaryExchangeRateTiersResponse, error) {
	ctx = appcode.WithContext(ctx, req.GetAppCode())
	tiers, err := s.svc.ListCoinSellerSalaryExchangeRateTiers(ctx, req.GetAppCode(), req.GetRegionId(), req.GetIncludeDisabled())
	if err != nil {
		return nil, xerr.ToGRPCError(err)
	}
	response := &walletv1.ListCoinSellerSalaryExchangeRateTiersResponse{Tiers: make([]*walletv1.CoinSellerSalaryExchangeRateTier, 0, len(tiers))}
	for _, tier := range tiers {
		response.Tiers = append(response.Tiers, &walletv1.CoinSellerSalaryExchangeRateTier{
			RegionId:    tier.RegionID,
			MinUsdMinor: tier.MinUSDMinor,
			MaxUsdMinor: tier.MaxUSDMinor,
			CoinPerUsd:  tier.CoinPerUSD,
			Status:      tier.Status,
			SortOrder:   int32(tier.SortOrder),
			UpdatedAtMs: tier.UpdatedAtMS,
		})
	}
	return response, nil
}

// ExchangeSalaryToCoin 处理用户工资兑换普通金币，身份资产已经由 gateway 校验并注入。
func (s *Server) ExchangeSalaryToCoin(ctx context.Context, req *walletv1.ExchangeSalaryToCoinRequest) (*walletv1.ExchangeSalaryToCoinResponse, error) {
	ctx = appcode.WithContext(ctx, req.GetAppCode())
	receipt, err := s.svc.ExchangeSalaryToCoin(ctx, ledger.SalaryExchangeCommand{
		AppCode:         req.GetAppCode(),
		CommandID:       req.GetCommandId(),
		UserID:          req.GetUserId(),
		SalaryAssetType: req.GetSalaryAssetType(),
		SalaryUSDMinor:  req.GetSalaryUsdMinor(),
		Reason:          req.GetReason(),
	})
	if err != nil {
		return nil, xerr.ToGRPCError(err)
	}
	return &walletv1.ExchangeSalaryToCoinResponse{
		TransactionId:      receipt.TransactionID,
		SalaryBalanceAfter: receipt.SalaryBalanceAfter,
		CoinBalanceAfter:   receipt.CoinBalanceAfter,
		SalaryUsdMinor:     receipt.SalaryUSDMinor,
		CoinAmount:         receipt.CoinAmount,
		CoinPerUsd:         receipt.CoinPerUSD,
	}, nil
}

// TransferSalaryToCoinSeller 处理用户工资转同区域币商专用金币库存。
func (s *Server) TransferSalaryToCoinSeller(ctx context.Context, req *walletv1.TransferSalaryToCoinSellerRequest) (*walletv1.TransferSalaryToCoinSellerResponse, error) {
	ctx = appcode.WithContext(ctx, req.GetAppCode())
	receipt, err := s.svc.TransferSalaryToCoinSeller(ctx, ledger.SalaryTransferToCoinSellerCommand{
		AppCode:         req.GetAppCode(),
		CommandID:       req.GetCommandId(),
		SourceUserID:    req.GetSourceUserId(),
		SellerUserID:    req.GetSellerUserId(),
		SalaryAssetType: req.GetSalaryAssetType(),
		SalaryUSDMinor:  req.GetSalaryUsdMinor(),
		RegionID:        req.GetRegionId(),
		Reason:          req.GetReason(),
	})
	if err != nil {
		return nil, xerr.ToGRPCError(err)
	}
	return &walletv1.TransferSalaryToCoinSellerResponse{
		TransactionId:            receipt.TransactionID,
		SourceSalaryBalanceAfter: receipt.SourceSalaryBalanceAfter,
		SellerBalanceAfter:       receipt.SellerBalanceAfter,
		SalaryUsdMinor:           receipt.SalaryUSDMinor,
		CoinAmount:               receipt.CoinAmount,
		CoinPerUsd:               receipt.CoinPerUSD,
		RateMinUsdMinor:          receipt.RateMinUSDMinor,
		RateMaxUsdMinor:          receipt.RateMaxUSDMinor,
	}, nil
}
