package grpc

import (
	"context"

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

// FreezePointWithdrawal 处理 POINT 提现申请提交前的积分冻结，调用方负责用户身份和提现地址校验。
func (s *Server) FreezePointWithdrawal(ctx context.Context, req *walletv1.FreezePointWithdrawalRequest) (*walletv1.FreezePointWithdrawalResponse, error) {
	ctx = appcode.WithContext(ctx, req.GetAppCode())
	receipt, err := s.svc.FreezePointWithdrawal(ctx, ledger.PointWithdrawalCommand{
		AppCode:          req.GetAppCode(),
		CommandID:        req.GetCommandId(),
		UserID:           req.GetUserId(),
		AssetType:        req.GetAssetType(),
		GrossPointAmount: req.GetGrossPointAmount(),
		GrossUSDMinor:    req.GetGrossUsdMinor(),
		FeePointAmount:   req.GetFeePointAmount(),
		NetPointAmount:   req.GetNetPointAmount(),
		PointsPerUSD:     req.GetPointsPerUsd(),
		FeeBPS:           int64(req.GetFeeBps()),
		Reason:           req.GetReason(),
		WithdrawalRef:    req.GetWithdrawalRef(),
		RegionID:         req.GetRegionId(),
	})
	if err != nil {
		return nil, xerr.ToGRPCError(err)
	}
	return &walletv1.FreezePointWithdrawalResponse{
		TransactionId:      receipt.TransactionID,
		Balance:            pointWithdrawalBalance(receipt),
		GrossPointAmount:   receipt.GrossPointAmount,
		FeePointAmount:     receipt.FeePointAmount,
		NetPointAmount:     receipt.NetPointAmount,
		PointsPerUsd:       receipt.PointsPerUSD,
		FeeBps:             int32(receipt.FeeBPS),
		PolicyInstanceCode: receipt.PointPolicyInstanceCode,
		GrossUsdMinor:      receipt.GrossUSDMinor,
		FeeUsdMinor:        receipt.FeeUSDMinor,
		NetUsdMinor:        receipt.NetUSDMinor,
		PolicyId:           receipt.PointPolicyID,
		PolicyVersion:      receipt.PointPolicyVersion,
		CoinsPerUsd:        receipt.CoinsPerUSD,
	}, nil
}

// SettlePointWithdrawal 在后台审核通过后扣掉 frozen 积分；失败时 admin 不应更新申请终态。
func (s *Server) SettlePointWithdrawal(ctx context.Context, req *walletv1.SettlePointWithdrawalRequest) (*walletv1.SettlePointWithdrawalResponse, error) {
	ctx = appcode.WithContext(ctx, req.GetAppCode())
	receipt, err := s.svc.SettlePointWithdrawal(ctx, ledger.PointWithdrawalCommand{
		AppCode:                 req.GetAppCode(),
		CommandID:               req.GetCommandId(),
		UserID:                  req.GetUserId(),
		AssetType:               req.GetAssetType(),
		GrossPointAmount:        req.GetGrossPointAmount(),
		FeePointAmount:          req.GetFeePointAmount(),
		NetPointAmount:          req.GetNetPointAmount(),
		PointsPerUSD:            req.GetPointsPerUsd(),
		FeeBPS:                  int64(req.GetFeeBps()),
		OperatorUserID:          req.GetOperatorUserId(),
		Reason:                  req.GetReason(),
		WithdrawalApplicationID: req.GetWithdrawalApplicationId(),
		FreezeTransactionID:     req.GetFreezeTransactionId(),
	})
	if err != nil {
		return nil, xerr.ToGRPCError(err)
	}
	return &walletv1.SettlePointWithdrawalResponse{
		TransactionId:    receipt.TransactionID,
		Balance:          pointWithdrawalBalance(receipt),
		GrossPointAmount: receipt.GrossPointAmount,
		FeePointAmount:   receipt.FeePointAmount,
		NetPointAmount:   receipt.NetPointAmount,
		PointsPerUsd:     receipt.PointsPerUSD,
		FeeBps:           int32(receipt.FeeBPS),
	}, nil
}

// ReleasePointWithdrawal 在后台拒绝或申请创建回滚时释放 frozen 积分回 available。
func (s *Server) ReleasePointWithdrawal(ctx context.Context, req *walletv1.ReleasePointWithdrawalRequest) (*walletv1.ReleasePointWithdrawalResponse, error) {
	ctx = appcode.WithContext(ctx, req.GetAppCode())
	receipt, err := s.svc.ReleasePointWithdrawal(ctx, ledger.PointWithdrawalCommand{
		AppCode:                 req.GetAppCode(),
		CommandID:               req.GetCommandId(),
		UserID:                  req.GetUserId(),
		AssetType:               req.GetAssetType(),
		GrossPointAmount:        req.GetGrossPointAmount(),
		FeePointAmount:          req.GetFeePointAmount(),
		NetPointAmount:          req.GetNetPointAmount(),
		PointsPerUSD:            req.GetPointsPerUsd(),
		FeeBPS:                  int64(req.GetFeeBps()),
		OperatorUserID:          req.GetOperatorUserId(),
		Reason:                  req.GetReason(),
		WithdrawalApplicationID: req.GetWithdrawalApplicationId(),
		FreezeTransactionID:     req.GetFreezeTransactionId(),
		WithdrawalRef:           req.GetWithdrawalRef(),
	})
	if err != nil {
		return nil, xerr.ToGRPCError(err)
	}
	return &walletv1.ReleasePointWithdrawalResponse{
		TransactionId:    receipt.TransactionID,
		Balance:          pointWithdrawalBalance(receipt),
		GrossPointAmount: receipt.GrossPointAmount,
		FeePointAmount:   receipt.FeePointAmount,
		NetPointAmount:   receipt.NetPointAmount,
		PointsPerUsd:     receipt.PointsPerUSD,
		FeeBps:           int32(receipt.FeeBPS),
	}, nil
}

func pointWithdrawalBalance(receipt ledger.PointWithdrawalReceipt) *walletv1.AssetBalance {
	return &walletv1.AssetBalance{
		AssetType:       receipt.AssetType,
		AvailableAmount: receipt.AvailableAfter,
		FrozenAmount:    receipt.FrozenAfter,
		Version:         receipt.Version,
	}
}
