package activityapi

import (
	"net/http"

	activityv1 "hyapp.local/api/proto/activity/v1"
	userv1 "hyapp.local/api/proto/user/v1"
	"hyapp/services/gateway-service/internal/auth"
	"hyapp/services/gateway-service/internal/transport/http/httpkit"
)

type cumulativeRechargeRewardUserData struct {
	UserID        int64  `json:"user_id"`
	DisplayUserID string `json:"display_user_id"`
	Username      string `json:"username"`
	Avatar        string `json:"avatar"`
}

type cumulativeRechargeRewardPeriodData struct {
	StartMS int64 `json:"start_ms"`
	EndMS   int64 `json:"end_ms"`
}

type cumulativeRechargeRewardTierData struct {
	TierID            int64                              `json:"tier_id"`
	TierCode          string                             `json:"tier_code"`
	TierName          string                             `json:"tier_name"`
	ThresholdUSDMinor int64                              `json:"threshold_usd_minor"`
	ResourceGroupID   int64                              `json:"resource_group_id"`
	ResourceGroup     *checkinResourceGroupData          `json:"resource_group,omitempty"`
	Status            string                             `json:"status"`
	SortOrder         int32                              `json:"sort_order"`
	Reached           bool                               `json:"reached"`
	Grant             *cumulativeRechargeRewardGrantData `json:"grant,omitempty"`
}

type cumulativeRechargeRewardProgressData struct {
	TotalUSDMinor int64 `json:"total_usd_minor"`
	UpdatedAtMS   int64 `json:"updated_at_ms"`
}

type cumulativeRechargeRewardGrantData struct {
	GrantID            string `json:"grant_id"`
	EventID            string `json:"event_id"`
	TransactionID      string `json:"transaction_id"`
	CommandID          string `json:"command_id"`
	UserID             int64  `json:"user_id"`
	TierID             int64  `json:"tier_id"`
	TierCode           string `json:"tier_code"`
	ThresholdUSDMinor  int64  `json:"threshold_usd_minor"`
	ResourceGroupID    int64  `json:"resource_group_id"`
	ReachedUSDMinor    int64  `json:"reached_usd_minor"`
	QualifyingUSDMinor int64  `json:"qualifying_usd_minor"`
	RechargeCoinAmount int64  `json:"recharge_coin_amount"`
	RechargeType       string `json:"recharge_type"`
	Status             string `json:"status"`
	WalletCommandID    string `json:"wallet_command_id"`
	WalletGrantID      string `json:"wallet_grant_id"`
	FailureReason      string `json:"failure_reason"`
	GrantedAtMS        int64  `json:"granted_at_ms"`
	CreatedAtMS        int64  `json:"created_at_ms"`
	UpdatedAtMS        int64  `json:"updated_at_ms"`
}

type cumulativeRechargeRewardStatusData struct {
	Enabled      bool                                 `json:"enabled"`
	User         cumulativeRechargeRewardUserData     `json:"user"`
	CycleKey     string                               `json:"cycle_key"`
	Period       cumulativeRechargeRewardPeriodData   `json:"period"`
	Tiers        []cumulativeRechargeRewardTierData   `json:"tiers"`
	Progress     cumulativeRechargeRewardProgressData `json:"progress"`
	Grants       []cumulativeRechargeRewardGrantData  `json:"grants"`
	ServerTimeMS int64                                `json:"server_time_ms"`
}

// getCumulativeRechargeRewardStatus 返回当前用户本 UTC 周期累充面板；累计与发放事实只读 activity-service，gateway 只补展示依赖。
func (h *Handler) getCumulativeRechargeRewardStatus(writer http.ResponseWriter, request *http.Request) {
	if h.cumulativeRecharge == nil {
		httpkit.WriteError(writer, request, http.StatusBadGateway, httpkit.CodeUpstreamError, "upstream service error")
		return
	}
	userID := auth.UserIDFromContext(request.Context())
	resp, err := h.cumulativeRecharge.GetCumulativeRechargeRewardStatus(request.Context(), &activityv1.GetCumulativeRechargeRewardStatusRequest{
		Meta:   httpkit.ActivityMeta(request),
		UserId: userID,
	})
	if err != nil {
		httpkit.WriteRPCError(writer, request, err)
		return
	}

	status := resp.GetStatus()
	// activity-service 只保存 resource_group_id；gateway 负责补资源组展示素材，避免活动服务依赖 H5 展示结构。
	groups, ok := h.resolveCheckinResourceGroups(writer, request, cumulativeRechargeRewardGroupIDs(status))
	if !ok {
		return
	}
	userData := cumulativeRechargeRewardUserData{UserID: userID}
	if h.userProfileClient != nil {
		// 用户资料是 H5 展示信息，读取失败时不影响活动金额和发放状态返回。
		if userResp, userErr := h.userProfileClient.BatchGetUsers(request.Context(), &userv1.BatchGetUsersRequest{
			Meta:    httpkit.UserMeta(request, ""),
			UserIds: []int64{userID},
		}); userErr == nil {
			userData = cumulativeRechargeRewardUserFromProto(userResp.GetUsers()[userID], userID)
		}
	}

	httpkit.WriteOK(writer, request, cumulativeRechargeRewardStatusFromProto(status, userData, groups))
}

func cumulativeRechargeRewardStatusFromProto(item *activityv1.CumulativeRechargeRewardStatus, user cumulativeRechargeRewardUserData, groups map[int64]checkinResourceGroupData) cumulativeRechargeRewardStatusData {
	if item == nil {
		return cumulativeRechargeRewardStatusData{
			User:   user,
			Tiers:  []cumulativeRechargeRewardTierData{},
			Grants: []cumulativeRechargeRewardGrantData{},
		}
	}
	grants := make([]cumulativeRechargeRewardGrantData, 0, len(item.GetGrants()))
	grantsByTierID := make(map[int64]cumulativeRechargeRewardGrantData, len(item.GetGrants()))
	for _, grant := range item.GetGrants() {
		// grant 按 tier_id 回填到档位，H5 可以直接渲染每个档位的 reached/granted/failed 状态。
		converted := cumulativeRechargeRewardGrantFromProto(grant)
		grants = append(grants, converted)
		grantsByTierID[converted.TierID] = converted
	}
	tiers := make([]cumulativeRechargeRewardTierData, 0, len(item.GetConfig().GetTiers()))
	for _, tier := range item.GetConfig().GetTiers() {
		converted := cumulativeRechargeRewardTierFromProto(tier, item.GetProgress().GetTotalUsdMinor(), groups)
		if grant, ok := grantsByTierID[converted.TierID]; ok {
			converted.Grant = &grant
		}
		tiers = append(tiers, converted)
	}
	return cumulativeRechargeRewardStatusData{
		Enabled:  item.GetConfig().GetEnabled(),
		User:     user,
		CycleKey: item.GetCycleKey(),
		Period: cumulativeRechargeRewardPeriodData{
			StartMS: item.GetPeriodStartMs(),
			EndMS:   item.GetPeriodEndMs(),
		},
		Tiers: tiers,
		Progress: cumulativeRechargeRewardProgressData{
			TotalUSDMinor: item.GetProgress().GetTotalUsdMinor(),
			UpdatedAtMS:   item.GetProgress().GetUpdatedAtMs(),
		},
		Grants:       grants,
		ServerTimeMS: item.GetServerTimeMs(),
	}
}

func cumulativeRechargeRewardTierFromProto(item *activityv1.CumulativeRechargeRewardTier, totalUSDMinor int64, groups map[int64]checkinResourceGroupData) cumulativeRechargeRewardTierData {
	if item == nil {
		return cumulativeRechargeRewardTierData{}
	}
	data := cumulativeRechargeRewardTierData{
		TierID:            item.GetTierId(),
		TierCode:          item.GetTierCode(),
		TierName:          item.GetTierName(),
		ThresholdUSDMinor: item.GetThresholdUsdMinor(),
		ResourceGroupID:   item.GetResourceGroupId(),
		Status:            item.GetStatus(),
		SortOrder:         item.GetSortOrder(),
		Reached:           totalUSDMinor >= item.GetThresholdUsdMinor(),
	}
	if group, ok := groups[item.GetResourceGroupId()]; ok {
		data.ResourceGroup = &group
	}
	return data
}

func cumulativeRechargeRewardGrantFromProto(item *activityv1.CumulativeRechargeRewardGrant) cumulativeRechargeRewardGrantData {
	if item == nil {
		return cumulativeRechargeRewardGrantData{}
	}
	return cumulativeRechargeRewardGrantData{
		GrantID:            item.GetGrantId(),
		EventID:            item.GetEventId(),
		TransactionID:      item.GetTransactionId(),
		CommandID:          item.GetCommandId(),
		UserID:             item.GetUserId(),
		TierID:             item.GetTierId(),
		TierCode:           item.GetTierCode(),
		ThresholdUSDMinor:  item.GetThresholdUsdMinor(),
		ResourceGroupID:    item.GetResourceGroupId(),
		ReachedUSDMinor:    item.GetReachedUsdMinor(),
		QualifyingUSDMinor: item.GetQualifyingUsdMinor(),
		RechargeCoinAmount: item.GetRechargeCoinAmount(),
		RechargeType:       item.GetRechargeType(),
		Status:             item.GetStatus(),
		WalletCommandID:    item.GetWalletCommandId(),
		WalletGrantID:      item.GetWalletGrantId(),
		FailureReason:      item.GetFailureReason(),
		GrantedAtMS:        item.GetGrantedAtMs(),
		CreatedAtMS:        item.GetCreatedAtMs(),
		UpdatedAtMS:        item.GetUpdatedAtMs(),
	}
}

func cumulativeRechargeRewardGroupIDs(item *activityv1.CumulativeRechargeRewardStatus) []int64 {
	if item == nil || item.GetConfig() == nil {
		return nil
	}
	ids := make([]int64, 0, len(item.GetConfig().GetTiers()))
	for _, tier := range item.GetConfig().GetTiers() {
		if tier.GetResourceGroupId() > 0 {
			ids = append(ids, tier.GetResourceGroupId())
		}
	}
	return ids
}

func cumulativeRechargeRewardUserFromProto(item *userv1.User, fallbackUserID int64) cumulativeRechargeRewardUserData {
	if item == nil {
		return cumulativeRechargeRewardUserData{UserID: fallbackUserID}
	}
	return cumulativeRechargeRewardUserData{
		UserID:        item.GetUserId(),
		DisplayUserID: item.GetDisplayUserId(),
		Username:      item.GetUsername(),
		Avatar:        item.GetAvatar(),
	}
}
