package grpc

import (
	"context"

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

// DebitCPBreakupFee 扣除解除 CP/兄弟/姐妹关系费用；关系状态确认由 user-service 负责。
func (s *Server) DebitCPBreakupFee(ctx context.Context, req *walletv1.DebitCPBreakupFeeRequest) (*walletv1.DebitCPBreakupFeeResponse, error) {
	ctx = appcode.WithContext(ctx, req.GetAppCode())
	receipt, err := s.svc.DebitCPBreakupFee(ctx, ledger.CPBreakupFeeCommand{
		AppCode:        req.GetAppCode(),
		CommandID:      req.GetCommandId(),
		UserID:         req.GetUserId(),
		RelationshipID: req.GetRelationshipId(),
		RelationType:   req.GetRelationType(),
		Amount:         req.GetAmount(),
	})
	if err != nil {
		return nil, xerr.ToGRPCError(err)
	}
	return &walletv1.DebitCPBreakupFeeResponse{
		TransactionId:    receipt.TransactionID,
		CoinSpent:        receipt.CoinSpent,
		CoinBalanceAfter: receipt.CoinBalanceAfter,
		Balance:          balanceToProto(receipt.Balance),
	}, nil
}

// DebitWheelDraw 扣除转盘抽奖金币；中奖结果不在 wallet 内生成，避免钱包反向拥有活动规则。
func (s *Server) DebitWheelDraw(ctx context.Context, req *walletv1.DebitWheelDrawRequest) (*walletv1.DebitWheelDrawResponse, error) {
	ctx = appcode.WithContext(ctx, req.GetAppCode())
	receipt, err := s.svc.DebitWheelDraw(ctx, ledger.WheelDrawDebitCommand{
		AppCode:   req.GetAppCode(),
		CommandID: req.GetCommandId(),
		UserID:    req.GetUserId(),
		WheelID:   req.GetWheelId(),
		DrawCount: req.GetDrawCount(),
		Amount:    req.GetAmount(),
	})
	if err != nil {
		return nil, xerr.ToGRPCError(err)
	}
	return &walletv1.DebitWheelDrawResponse{
		TransactionId:    receipt.TransactionID,
		CoinSpent:        receipt.CoinSpent,
		CoinBalanceAfter: receipt.CoinBalanceAfter,
		Balance:          balanceToProto(receipt.Balance),
	}, nil
}

// CreditTaskReward 处理 activity-service 任务奖励金币入账。
func (s *Server) CreditTaskReward(ctx context.Context, req *walletv1.CreditTaskRewardRequest) (*walletv1.CreditTaskRewardResponse, error) {
	ctx = appcode.WithContext(ctx, req.GetAppCode())
	receipt, err := s.svc.CreditTaskReward(ctx, ledger.TaskRewardCommand{
		AppCode:      req.GetAppCode(),
		CommandID:    req.GetCommandId(),
		TargetUserID: req.GetTargetUserId(),
		AssetType:    req.GetRewardAssetType(),
		Amount:       req.GetAmount(),
		TaskType:     req.GetTaskType(),
		TaskID:       req.GetTaskId(),
		CycleKey:     req.GetCycleKey(),
		Reason:       req.GetReason(),
	})
	if err != nil {
		return nil, xerr.ToGRPCError(err)
	}

	return &walletv1.CreditTaskRewardResponse{
		TransactionId: receipt.TransactionID,
		Amount:        receipt.Amount,
		GrantedAtMs:   receipt.GrantedAtMS,
		Balance: &walletv1.AssetBalance{
			AppCode:         receipt.Balance.AppCode,
			AssetType:       receipt.Balance.AssetType,
			AvailableAmount: receipt.Balance.AvailableAmount,
			FrozenAmount:    receipt.Balance.FrozenAmount,
			Version:         receipt.Balance.Version,
		},
	}, nil
}

// CreditLuckyGiftReward 处理 activity-service 幸运礼物抽奖 outbox 的中奖金币入账。
func (s *Server) CreditLuckyGiftReward(ctx context.Context, req *walletv1.CreditLuckyGiftRewardRequest) (*walletv1.CreditLuckyGiftRewardResponse, error) {
	ctx = appcode.WithContext(ctx, req.GetAppCode())
	receipt, err := s.svc.CreditLuckyGiftReward(ctx, ledger.LuckyGiftRewardCommand{
		AppCode:         req.GetAppCode(),
		CommandID:       req.GetCommandId(),
		TargetUserID:    req.GetTargetUserId(),
		Amount:          req.GetAmount(),
		DrawID:          req.GetDrawId(),
		RoomID:          req.GetRoomId(),
		VisibleRegionID: req.GetVisibleRegionId(),
		CountryID:       req.GetCountryId(),
		GiftID:          req.GetGiftId(),
		PoolID:          req.GetPoolId(),
		Reason:          req.GetReason(),
	})
	if err != nil {
		return nil, xerr.ToGRPCError(err)
	}

	return &walletv1.CreditLuckyGiftRewardResponse{
		TransactionId: receipt.TransactionID,
		Amount:        receipt.Amount,
		GrantedAtMs:   receipt.GrantedAtMS,
		Balance: &walletv1.AssetBalance{
			AppCode:         receipt.Balance.AppCode,
			AssetType:       receipt.Balance.AssetType,
			AvailableAmount: receipt.Balance.AvailableAmount,
			FrozenAmount:    receipt.Balance.FrozenAmount,
			Version:         receipt.Balance.Version,
		},
	}, nil
}

// CreditWheelReward 处理 activity-service 转盘金币奖品 outbox 的入账。
func (s *Server) CreditWheelReward(ctx context.Context, req *walletv1.CreditWheelRewardRequest) (*walletv1.CreditWheelRewardResponse, error) {
	ctx = appcode.WithContext(ctx, req.GetAppCode())
	receipt, err := s.svc.CreditWheelReward(ctx, ledger.WheelRewardCommand{
		AppCode:         req.GetAppCode(),
		CommandID:       req.GetCommandId(),
		TargetUserID:    req.GetTargetUserId(),
		Amount:          req.GetAmount(),
		DrawID:          req.GetDrawId(),
		WheelID:         req.GetWheelId(),
		SelectedTierID:  req.GetSelectedTierId(),
		VisibleRegionID: req.GetVisibleRegionId(),
		Reason:          req.GetReason(),
	})
	if err != nil {
		return nil, xerr.ToGRPCError(err)
	}

	return &walletv1.CreditWheelRewardResponse{
		TransactionId: receipt.TransactionID,
		Amount:        receipt.Amount,
		GrantedAtMs:   receipt.GrantedAtMS,
		Balance: &walletv1.AssetBalance{
			AppCode:         receipt.Balance.AppCode,
			AssetType:       receipt.Balance.AssetType,
			AvailableAmount: receipt.Balance.AvailableAmount,
			FrozenAmount:    receipt.Balance.FrozenAmount,
			Version:         receipt.Balance.Version,
		},
	}, nil
}

// CreditRoomTurnoverReward 处理 activity-service 每周房间流水奖励金币入账。
func (s *Server) CreditRoomTurnoverReward(ctx context.Context, req *walletv1.CreditRoomTurnoverRewardRequest) (*walletv1.CreditRoomTurnoverRewardResponse, error) {

	ctx = appcode.WithContext(ctx, req.GetAppCode())
	receipt, err := s.svc.CreditRoomTurnoverReward(ctx, ledger.RoomTurnoverRewardCommand{
		AppCode:       req.GetAppCode(),
		CommandID:     req.GetCommandId(),
		TargetUserID:  req.GetTargetUserId(),
		Amount:        req.GetAmount(),
		SettlementID:  req.GetSettlementId(),
		RoomID:        req.GetRoomId(),
		PeriodStartMS: req.GetPeriodStartMs(),
		PeriodEndMS:   req.GetPeriodEndMs(),
		CoinSpent:     req.GetCoinSpent(),
		TierID:        req.GetTierId(),
		TierCode:      req.GetTierCode(),
		Reason:        req.GetReason(),
	})
	if err != nil {
		return nil, xerr.ToGRPCError(err)
	}

	return &walletv1.CreditRoomTurnoverRewardResponse{
		TransactionId: receipt.TransactionID,
		Amount:        receipt.Amount,
		GrantedAtMs:   receipt.GrantedAtMS,
		Balance: &walletv1.AssetBalance{
			AppCode:         receipt.Balance.AppCode,
			AssetType:       receipt.Balance.AssetType,
			AvailableAmount: receipt.Balance.AvailableAmount,
			FrozenAmount:    receipt.Balance.FrozenAmount,
			Version:         receipt.Balance.Version,
		},
	}, nil
}

// CreditInviteActivityReward 处理 activity-service 邀请活动奖励金币入账。
func (s *Server) CreditInviteActivityReward(ctx context.Context, req *walletv1.CreditInviteActivityRewardRequest) (*walletv1.CreditInviteActivityRewardResponse, error) {
	ctx = appcode.WithContext(ctx, req.GetAppCode())
	receipt, err := s.svc.CreditInviteActivityReward(ctx, ledger.InviteActivityRewardCommand{
		AppCode:      req.GetAppCode(),
		CommandID:    req.GetCommandId(),
		TargetUserID: req.GetTargetUserId(),
		Amount:       req.GetAmount(),
		ClaimID:      req.GetClaimId(),
		RewardType:   req.GetRewardType(),
		TierID:       req.GetTierId(),
		TierCode:     req.GetTierCode(),
		CycleKey:     req.GetCycleKey(),
		ReachedValue: req.GetReachedValue(),
		Reason:       req.GetReason(),
	})
	if err != nil {
		return nil, xerr.ToGRPCError(err)
	}

	return &walletv1.CreditInviteActivityRewardResponse{
		TransactionId: receipt.TransactionID,
		Amount:        receipt.Amount,
		GrantedAtMs:   receipt.GrantedAtMS,
		Balance: &walletv1.AssetBalance{
			AppCode:         receipt.Balance.AppCode,
			AssetType:       receipt.Balance.AssetType,
			AvailableAmount: receipt.Balance.AvailableAmount,
			FrozenAmount:    receipt.Balance.FrozenAmount,
			Version:         receipt.Balance.Version,
		},
	}, nil
}

// CreditAgencyOpeningReward 处理 activity-service 代理开业流水档位奖励金币入账。
func (s *Server) CreditAgencyOpeningReward(ctx context.Context, req *walletv1.CreditAgencyOpeningRewardRequest) (*walletv1.CreditAgencyOpeningRewardResponse, error) {
	ctx = appcode.WithContext(ctx, req.GetAppCode())
	receipt, err := s.svc.CreditAgencyOpeningReward(ctx, ledger.AgencyOpeningRewardCommand{
		AppCode:       req.GetAppCode(),
		CommandID:     req.GetCommandId(),
		TargetUserID:  req.GetTargetUserId(),
		Amount:        req.GetAmount(),
		ApplicationID: req.GetApplicationId(),
		CycleID:       req.GetCycleId(),
		AgencyID:      req.GetAgencyId(),
		RankNo:        req.GetRankNo(),
		ScoreCoins:    req.GetScoreCoins(),
		Reason:        req.GetReason(),
	})
	if err != nil {
		return nil, xerr.ToGRPCError(err)
	}

	return &walletv1.CreditAgencyOpeningRewardResponse{
		TransactionId: receipt.TransactionID,
		Amount:        receipt.Amount,
		GrantedAtMs:   receipt.GrantedAtMS,
		Balance: &walletv1.AssetBalance{
			AppCode:         receipt.Balance.AppCode,
			AssetType:       receipt.Balance.AssetType,
			AvailableAmount: receipt.Balance.AvailableAmount,
			FrozenAmount:    receipt.Balance.FrozenAmount,
			Version:         receipt.Balance.Version,
		},
	}, nil
}
