package grpc

import (
	"context"

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

// FreezeSalaryWithdrawal 处理 H5 提现申请提交前的工资冻结，调用方必须已完成用户身份校验。
func (s *Server) FreezeSalaryWithdrawal(ctx context.Context, req *walletv1.FreezeSalaryWithdrawalRequest) (*walletv1.FreezeSalaryWithdrawalResponse, error) {
	ctx = appcode.WithContext(ctx, req.GetAppCode())
	receipt, err := s.svc.FreezeSalaryWithdrawal(ctx, ledger.SalaryWithdrawalCommand{
		AppCode:         req.GetAppCode(),
		CommandID:       req.GetCommandId(),
		UserID:          req.GetUserId(),
		SalaryAssetType: req.GetSalaryAssetType(),
		SalaryUSDMinor:  req.GetSalaryUsdMinor(),
		Reason:          req.GetReason(),
		WithdrawalRef:   req.GetWithdrawalRef(),
		RegionID:        req.GetRegionId(),
	})
	if err != nil {
		return nil, xerr.ToGRPCError(err)
	}
	return &walletv1.FreezeSalaryWithdrawalResponse{
		TransactionId:  receipt.TransactionID,
		Balance:        salaryWithdrawalBalance(receipt),
		SalaryUsdMinor: receipt.SalaryUSDMinor,
	}, nil
}

// SettleSalaryWithdrawal 在后台审核通过后扣掉冻结工资；失败时 admin 不会更新申请终态。
func (s *Server) SettleSalaryWithdrawal(ctx context.Context, req *walletv1.SettleSalaryWithdrawalRequest) (*walletv1.SettleSalaryWithdrawalResponse, error) {
	ctx = appcode.WithContext(ctx, req.GetAppCode())
	receipt, err := s.svc.SettleSalaryWithdrawal(ctx, ledger.SalaryWithdrawalCommand{
		AppCode:                 req.GetAppCode(),
		CommandID:               req.GetCommandId(),
		UserID:                  req.GetUserId(),
		SalaryAssetType:         req.GetSalaryAssetType(),
		SalaryUSDMinor:          req.GetSalaryUsdMinor(),
		OperatorUserID:          req.GetOperatorUserId(),
		Reason:                  req.GetReason(),
		WithdrawalApplicationID: req.GetWithdrawalApplicationId(),
	})
	if err != nil {
		return nil, xerr.ToGRPCError(err)
	}
	return &walletv1.SettleSalaryWithdrawalResponse{
		TransactionId:  receipt.TransactionID,
		Balance:        salaryWithdrawalBalance(receipt),
		SalaryUsdMinor: receipt.SalaryUSDMinor,
	}, nil
}

// ReleaseSalaryWithdrawal 在后台拒绝或申请创建回滚时释放冻结工资回可用余额。
func (s *Server) ReleaseSalaryWithdrawal(ctx context.Context, req *walletv1.ReleaseSalaryWithdrawalRequest) (*walletv1.ReleaseSalaryWithdrawalResponse, error) {
	ctx = appcode.WithContext(ctx, req.GetAppCode())
	receipt, err := s.svc.ReleaseSalaryWithdrawal(ctx, ledger.SalaryWithdrawalCommand{
		AppCode:                 req.GetAppCode(),
		CommandID:               req.GetCommandId(),
		UserID:                  req.GetUserId(),
		SalaryAssetType:         req.GetSalaryAssetType(),
		SalaryUSDMinor:          req.GetSalaryUsdMinor(),
		OperatorUserID:          req.GetOperatorUserId(),
		Reason:                  req.GetReason(),
		WithdrawalApplicationID: req.GetWithdrawalApplicationId(),
	})
	if err != nil {
		return nil, xerr.ToGRPCError(err)
	}
	return &walletv1.ReleaseSalaryWithdrawalResponse{
		TransactionId:  receipt.TransactionID,
		Balance:        salaryWithdrawalBalance(receipt),
		SalaryUsdMinor: receipt.SalaryUSDMinor,
	}, nil
}

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