package grpc

import (
	"context"

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

// ListRechargeProducts 返回当前用户区域可用的充值渠道和档位。
func (s *Server) ListRechargeProducts(ctx context.Context, req *walletv1.ListRechargeProductsRequest) (*walletv1.ListRechargeProductsResponse, error) {
	ctx = appcode.WithContext(ctx, req.GetAppCode())
	products, channels, err := s.svc.ListRechargeProducts(ctx, req.GetUserId(), req.GetRegionId(), req.GetPlatform(), req.GetAudienceType())
	if err != nil {
		return nil, xerr.ToGRPCError(err)
	}
	resp := &walletv1.ListRechargeProductsResponse{Channels: channels, Products: make([]*walletv1.RechargeProduct, 0, len(products))}
	for _, product := range products {
		resp.Products = append(resp.Products, rechargeProductToProto(product))
	}
	return resp, nil
}

// ConfirmGooglePayment 校验 Google Play purchase token 并完成钱包入账。
func (s *Server) ConfirmGooglePayment(ctx context.Context, req *walletv1.ConfirmGooglePaymentRequest) (*walletv1.ConfirmGooglePaymentResponse, error) {
	ctx = appcode.WithContext(ctx, req.GetAppCode())
	receipt, err := s.svc.ConfirmGooglePayment(ctx, ledger.GooglePaymentCommand{
		AppCode:        req.GetAppCode(),
		CommandID:      req.GetCommandId(),
		UserID:         req.GetUserId(),
		RegionID:       req.GetRegionId(),
		CountryID:      req.GetCountryId(),
		ProductID:      req.GetProductId(),
		ProductCode:    req.GetProductCode(),
		PackageName:    req.GetPackageName(),
		PurchaseToken:  req.GetPurchaseToken(),
		OrderID:        req.GetOrderId(),
		PurchaseTimeMS: req.GetPurchaseTimeMs(),
	})
	if err != nil {
		return nil, xerr.ToGRPCError(err)
	}
	return &walletv1.ConfirmGooglePaymentResponse{
		PaymentOrderId:   receipt.PaymentOrderID,
		TransactionId:    receipt.TransactionID,
		Status:           receipt.Status,
		ProductId:        receipt.ProductID,
		ProductCode:      receipt.ProductCode,
		CoinAmount:       receipt.CoinAmount,
		Balance:          balanceToProto(receipt.Balance),
		IdempotentReplay: receipt.IdempotentReplay,
		ConsumeState:     receipt.ConsumeState,
	}, nil
}

// ListAdminRechargeProducts 返回后台内购配置列表。
func (s *Server) ListAdminRechargeProducts(ctx context.Context, req *walletv1.ListAdminRechargeProductsRequest) (*walletv1.ListAdminRechargeProductsResponse, error) {
	ctx = appcode.WithContext(ctx, req.GetAppCode())
	products, total, err := s.svc.ListAdminRechargeProducts(ctx, ledger.ListRechargeProductsQuery{
		AppCode:      req.GetAppCode(),
		Status:       req.GetStatus(),
		Platform:     req.GetPlatform(),
		RegionID:     req.GetRegionId(),
		Keyword:      req.GetKeyword(),
		Page:         req.GetPage(),
		PageSize:     req.GetPageSize(),
		AudienceType: req.GetAudienceType(),
	})
	if err != nil {
		return nil, xerr.ToGRPCError(err)
	}
	resp := &walletv1.ListAdminRechargeProductsResponse{Products: make([]*walletv1.RechargeProduct, 0, len(products)), Total: total}
	for _, product := range products {
		resp.Products = append(resp.Products, rechargeProductToProto(product))
	}
	return resp, nil
}

// CreateRechargeProduct 创建后台内购商品配置。
func (s *Server) CreateRechargeProduct(ctx context.Context, req *walletv1.CreateRechargeProductRequest) (*walletv1.RechargeProductResponse, error) {
	ctx = appcode.WithContext(ctx, req.GetAppCode())
	product, err := s.svc.CreateRechargeProduct(ctx, ledger.RechargeProductCommand{
		AppCode:        req.GetAppCode(),
		AmountMicro:    req.GetAmountMicro(),
		CoinAmount:     req.GetCoinAmount(),
		ProductName:    req.GetProductName(),
		Description:    req.GetDescription(),
		Platform:       req.GetPlatform(),
		RegionIDs:      req.GetRegionIds(),
		Enabled:        req.GetEnabled(),
		AppVisible:     req.AppVisible,
		OperatorUserID: req.GetOperatorUserId(),
		AudienceType:   req.GetAudienceType(),
	})
	if err != nil {
		return nil, xerr.ToGRPCError(err)
	}
	return &walletv1.RechargeProductResponse{Product: rechargeProductToProto(product)}, nil
}

// UpdateRechargeProduct 修改后台内购商品配置。
func (s *Server) UpdateRechargeProduct(ctx context.Context, req *walletv1.UpdateRechargeProductRequest) (*walletv1.RechargeProductResponse, error) {
	ctx = appcode.WithContext(ctx, req.GetAppCode())
	product, err := s.svc.UpdateRechargeProduct(ctx, ledger.RechargeProductCommand{
		AppCode:        req.GetAppCode(),
		ProductID:      req.GetProductId(),
		AmountMicro:    req.GetAmountMicro(),
		CoinAmount:     req.GetCoinAmount(),
		ProductName:    req.GetProductName(),
		Description:    req.GetDescription(),
		Platform:       req.GetPlatform(),
		RegionIDs:      req.GetRegionIds(),
		Enabled:        req.GetEnabled(),
		AppVisible:     req.AppVisible,
		OperatorUserID: req.GetOperatorUserId(),
		AudienceType:   req.GetAudienceType(),
	})
	if err != nil {
		return nil, xerr.ToGRPCError(err)
	}
	return &walletv1.RechargeProductResponse{Product: rechargeProductToProto(product)}, nil
}

// DeleteRechargeProduct 删除后台内购商品配置。
func (s *Server) DeleteRechargeProduct(ctx context.Context, req *walletv1.DeleteRechargeProductRequest) (*walletv1.DeleteRechargeProductResponse, error) {
	ctx = appcode.WithContext(ctx, req.GetAppCode())
	if err := s.svc.DeleteRechargeProduct(ctx, req.GetAppCode(), req.GetProductId()); err != nil {
		return nil, xerr.ToGRPCError(err)
	}
	return &walletv1.DeleteRechargeProductResponse{Deleted: true}, nil
}

func rechargeProductToProto(product ledger.RechargeProduct) *walletv1.RechargeProduct {
	return &walletv1.RechargeProduct{
		AppCode:           product.AppCode,
		AudienceType:      product.AudienceType,
		ProductId:         product.ProductID,
		ProductCode:       product.ProductCode,
		ProductName:       product.ProductName,
		Description:       product.Description,
		Platform:          product.Platform,
		Channel:           product.Channel,
		CurrencyCode:      product.CurrencyCode,
		AmountMicro:       product.AmountMicro,
		AmountMinor:       product.AmountMinor,
		CoinAmount:        product.CoinAmount,
		PolicyVersion:     product.PolicyVersion,
		Status:            product.Status,
		Enabled:           product.Enabled,
		AppVisible:        product.AppVisible,
		SortOrder:         product.SortOrder,
		RegionIds:         product.RegionIDs,
		ResourceAssetType: product.ResourceAssetType,
		CreatedByUserId:   product.CreatedByUserID,
		UpdatedByUserId:   product.UpdatedByUserID,
		CreatedAtMs:       product.CreatedAtMS,
		UpdatedAtMs:       product.UpdatedAtMS,
	}
}
