package grpc

import (
	"context"

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

// ListRechargeBills 暴露充值账单只读查询；后台 HTTP 层负责登录态和菜单权限。
func (s *Server) ListRechargeBills(ctx context.Context, req *walletv1.ListRechargeBillsRequest) (*walletv1.ListRechargeBillsResponse, error) {
	ctx = appcode.WithContext(ctx, req.GetAppCode())
	items, total, err := s.svc.ListRechargeBills(ctx, ledger.ListRechargeBillsQuery{
		AppCode:      req.GetAppCode(),
		UserID:       req.GetUserId(),
		SellerUserID: req.GetSellerUserId(),
		RegionID:     req.GetRegionId(),
		RechargeType: req.GetRechargeType(),
		Status:       req.GetStatus(),
		Keyword:      req.GetKeyword(),
		PaidState:    req.GetPaidState(),
		StartAtMS:    req.GetStartAtMs(),
		EndAtMS:      req.GetEndAtMs(),
		Page:         req.GetPage(),
		PageSize:     req.GetPageSize(),
	})
	if err != nil {
		return nil, xerr.ToGRPCError(err)
	}

	resp := &walletv1.ListRechargeBillsResponse{Bills: make([]*walletv1.RechargeBill, 0, len(items)), Total: total}
	for _, item := range items {
		resp.Bills = append(resp.Bills, rechargeBillToProto(item))
	}
	return resp, nil
}

// GetRechargeBillSummary 暴露充值账单聚合查询，筛选口径与列表完全一致。
func (s *Server) GetRechargeBillSummary(ctx context.Context, req *walletv1.GetRechargeBillSummaryRequest) (*walletv1.GetRechargeBillSummaryResponse, error) {
	ctx = appcode.WithContext(ctx, req.GetAppCode())
	summary, err := s.svc.GetRechargeBillSummary(ctx, ledger.ListRechargeBillsQuery{
		AppCode:      req.GetAppCode(),
		UserID:       req.GetUserId(),
		SellerUserID: req.GetSellerUserId(),
		RegionID:     req.GetRegionId(),
		RechargeType: req.GetRechargeType(),
		Status:       req.GetStatus(),
		Keyword:      req.GetKeyword(),
		StartAtMS:    req.GetStartAtMs(),
		EndAtMS:      req.GetEndAtMs(),
	})
	if err != nil {
		return nil, xerr.ToGRPCError(err)
	}
	return &walletv1.GetRechargeBillSummaryResponse{
		Total:      rechargeBillSummaryBucketToProto(summary.Total),
		GooglePlay: rechargeBillSummaryBucketToProto(summary.GooglePlay),
		ThirdParty: rechargeBillSummaryBucketToProto(summary.ThirdParty),
		CoinSeller: rechargeBillSummaryBucketToProto(summary.CoinSeller),
	}, nil
}

// BatchGetUserRechargeStats 只读取用户累计聚合表，避免后台详情按用户回扫充值账单。
func (s *Server) BatchGetUserRechargeStats(ctx context.Context, req *walletv1.BatchGetUserRechargeStatsRequest) (*walletv1.BatchGetUserRechargeStatsResponse, error) {
	ctx = appcode.WithContext(ctx, req.GetAppCode())
	items, err := s.svc.BatchGetUserRechargeStats(ctx, req.GetAppCode(), req.GetUserIds())
	if err != nil {
		return nil, xerr.ToGRPCError(err)
	}
	resp := &walletv1.BatchGetUserRechargeStatsResponse{Items: make([]*walletv1.UserRechargeStats, 0, len(items))}
	for _, item := range items {
		resp.Items = append(resp.Items, &walletv1.UserRechargeStats{
			UserId:              item.UserID,
			RechargeCount:       item.RechargeCount,
			TotalCoinAmount:     item.TotalCoinAmount,
			TotalUsdMinorAmount: item.TotalUSDMinorAmount,
			FirstRechargedAtMs:  item.FirstRechargedAtMS,
			UpdatedAtMs:         item.UpdatedAtMS,
		})
	}
	return resp, nil
}

// GetRechargeBillOverview 暴露财务概览聚合：按日趋势、区域分布与谷歌实付覆盖度。
func (s *Server) GetRechargeBillOverview(ctx context.Context, req *walletv1.GetRechargeBillOverviewRequest) (*walletv1.GetRechargeBillOverviewResponse, error) {
	ctx = appcode.WithContext(ctx, req.GetAppCode())
	overview, err := s.svc.GetRechargeBillOverview(ctx, ledger.ListRechargeBillsQuery{
		AppCode:      req.GetAppCode(),
		RegionID:     req.GetRegionId(),
		RechargeType: req.GetRechargeType(),
		Status:       req.GetStatus(),
		StartAtMS:    req.GetStartAtMs(),
		EndAtMS:      req.GetEndAtMs(),
	}, req.GetTzOffsetMinutes())
	if err != nil {
		return nil, xerr.ToGRPCError(err)
	}
	resp := &walletv1.GetRechargeBillOverviewResponse{
		Daily:   make([]*walletv1.RechargeBillDailyBucket, 0, len(overview.Daily)),
		Regions: make([]*walletv1.RechargeBillRegionBucket, 0, len(overview.Regions)),
		GooglePaid: &walletv1.RechargeBillGooglePaidStats{
			GoogleBillCount: overview.GooglePaid.GoogleBillCount,
			SyncedCount:     overview.GooglePaid.SyncedCount,
			UnsyncedCount:   overview.GooglePaid.UnsyncedCount,
			CoveredUsdMinor: overview.GooglePaid.CoveredUSDMinor,
			EstFeeUsdMinor:  overview.GooglePaid.EstFeeUSDMinor,
			EstTaxUsdMinor:  overview.GooglePaid.EstTaxUSDMinor,
			EstNetUsdMinor:  overview.GooglePaid.EstNetUSDMinor,
		},
		SalaryTransfer: &walletv1.RechargeBillSalaryTransferStats{
			TransferCount:    overview.SalaryTransfer.TransferCount,
			TransferUsdMinor: overview.SalaryTransfer.TransferUSDMinor,
		},
	}
	for _, bucket := range overview.Daily {
		resp.Daily = append(resp.Daily, &walletv1.RechargeBillDailyBucket{
			Date:                 bucket.Date,
			GoogleUsdMinor:       bucket.GoogleUSDMinor,
			ThirdPartyUsdMinor:   bucket.ThirdPartyUSDMinor,
			CoinSellerUsdMinor:   bucket.CoinSellerUSDMinor,
			GoogleCoinAmount:     bucket.GoogleCoinAmount,
			ThirdPartyCoinAmount: bucket.ThirdPartyCoinAmount,
			CoinSellerCoinAmount: bucket.CoinSellerCoinAmount,
		})
	}
	for _, bucket := range overview.Regions {
		resp.Regions = append(resp.Regions, &walletv1.RechargeBillRegionBucket{
			RegionId:       bucket.RegionID,
			BillCount:      bucket.BillCount,
			UsdMinorAmount: bucket.USDMinorAmount,
		})
	}
	return resp, nil
}

// RefreshGooglePaymentPrices 触发 Google Orders API 实付明细同步；单笔失败不阻断整批。
func (s *Server) RefreshGooglePaymentPrices(ctx context.Context, req *walletv1.RefreshGooglePaymentPricesRequest) (*walletv1.RefreshGooglePaymentPricesResponse, error) {
	ctx = appcode.WithContext(ctx, req.GetAppCode())
	results, err := s.svc.RefreshGooglePaymentPrices(ctx, req.GetAppCode(), req.GetTransactionIds())
	if err != nil {
		return nil, xerr.ToGRPCError(err)
	}
	resp := &walletv1.RefreshGooglePaymentPricesResponse{Prices: make([]*walletv1.GooglePaymentPrice, 0, len(results))}
	for _, result := range results {
		resp.Prices = append(resp.Prices, &walletv1.GooglePaymentPrice{
			TransactionId:   result.TransactionID,
			CurrencyCode:    result.CurrencyCode,
			PaidAmountMicro: result.PaidAmountMicro,
			TaxMicro:        result.TaxAmountMicro,
			NetMicro:        result.NetAmountMicro,
			SyncedAtMs:      result.SyncedAtMS,
			Error:           result.Err,
		})
	}
	return resp, nil
}

func rechargeBillSummaryBucketToProto(bucket ledger.RechargeBillSummaryBucket) *walletv1.RechargeBillSummaryBucket {
	return &walletv1.RechargeBillSummaryBucket{
		BillCount:      bucket.BillCount,
		CoinAmount:     bucket.CoinAmount,
		UsdMinorAmount: bucket.USDMinorAmount,
	}
}

func rechargeBillToProto(item ledger.RechargeBill) *walletv1.RechargeBill {
	return &walletv1.RechargeBill{
		AppCode:                item.AppCode,
		TransactionId:          item.TransactionID,
		CommandId:              item.CommandID,
		RechargeType:           item.RechargeType,
		Status:                 item.Status,
		ExternalRef:            item.ExternalRef,
		UserId:                 item.UserID,
		SellerUserId:           item.SellerUserID,
		SellerRegionId:         item.SellerRegionID,
		TargetRegionId:         item.TargetRegionID,
		PolicyId:               item.PolicyID,
		PolicyVersion:          item.PolicyVersion,
		CurrencyCode:           item.CurrencyCode,
		CoinAmount:             item.CoinAmount,
		UsdMinorAmount:         item.USDMinorAmount,
		ExchangeCoinAmount:     item.ExchangeCoinAmount,
		ExchangeUsdMinorAmount: item.ExchangeUSDMinorAmount,
		ProviderAmountMinor:    item.ProviderAmountMinor,
		CreatedAtMs:            item.CreatedAtMS,
		ProviderCode:           item.ProviderCode,
		UserPaidCurrencyCode:   item.UserPaidCurrencyCode,
		UserPaidAmountMicro:    item.UserPaidAmountMicro,
		ProviderFeeMicro:       item.ProviderFeeMicro,
		ProviderTaxMicro:       item.ProviderTaxMicro,
		ProviderNetMicro:       item.ProviderNetMicro,
		PaidSyncedAtMs:         item.PaidSyncedAtMS,
	}
}
