package activityapi

import (
	"net/http"

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

type roomTurnoverRewardTierData struct {
	TierID             int64  `json:"tier_id"`
	TierCode           string `json:"tier_code"`
	TierName           string `json:"tier_name"`
	ThresholdCoinSpent int64  `json:"threshold_coin_spent"`
	RewardCoinAmount   int64  `json:"reward_coin_amount"`
	Status             string `json:"status"`
	SortOrder          int32  `json:"sort_order"`
}

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

type roomTurnoverRewardRoomData struct {
	HasRoom     bool   `json:"has_room"`
	RoomID      string `json:"room_id"`
	OwnerUserID int64  `json:"owner_user_id"`
	RegionID    int64  `json:"region_id"`
	Title       string `json:"title"`
	CoverURL    string `json:"cover_url"`
}

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

type roomTurnoverRewardSettlementData struct {
	SettlementID        string `json:"settlement_id"`
	RegionID            int64  `json:"region_id"`
	RoomID              string `json:"room_id"`
	OwnerUserID         int64  `json:"owner_user_id"`
	PeriodStartMS       int64  `json:"period_start_ms"`
	PeriodEndMS         int64  `json:"period_end_ms"`
	CoinSpent           int64  `json:"coin_spent"`
	TierID              int64  `json:"tier_id"`
	TierCode            string `json:"tier_code"`
	ThresholdCoinSpent  int64  `json:"threshold_coin_spent"`
	RewardCoinAmount    int64  `json:"reward_coin_amount"`
	Status              string `json:"status"`
	WalletCommandID     string `json:"wallet_command_id"`
	WalletTransactionID string `json:"wallet_transaction_id"`
	FailureReason       string `json:"failure_reason"`
	SettledAtMS         int64  `json:"settled_at_ms"`
	CreatedAtMS         int64  `json:"created_at_ms"`
	UpdatedAtMS         int64  `json:"updated_at_ms"`
}

type roomTurnoverRewardStatusData struct {
	Enabled                  bool                              `json:"enabled"`
	User                     roomTurnoverRewardUserData        `json:"user"`
	Room                     roomTurnoverRewardRoomData        `json:"room"`
	Period                   roomTurnoverRewardPeriodData      `json:"period"`
	Tiers                    []roomTurnoverRewardTierData      `json:"tiers"`
	CurrentCoinSpent         int64                             `json:"current_coin_spent"`
	ExpectedRewardCoinAmount int64                             `json:"expected_reward_coin_amount"`
	MatchedTier              *roomTurnoverRewardTierData       `json:"matched_tier,omitempty"`
	LatestSettlement         *roomTurnoverRewardSettlementData `json:"latest_settlement,omitempty"`
	ServerTimeMS             int64                             `json:"server_time_ms"`
}

func (h *Handler) getRoomTurnoverRewardStatus(writer http.ResponseWriter, request *http.Request) {
	if h.roomTurnoverReward == nil || h.roomQueryClient == nil {
		httpkit.WriteError(writer, request, http.StatusBadGateway, httpkit.CodeUpstreamError, "upstream service error")
		return
	}

	userID := auth.UserIDFromContext(request.Context())
	roomData := roomTurnoverRewardRoomData{OwnerUserID: userID}
	// App 接口按“当前登录用户自己的房间”展示活动进度；gateway 只编排 room-service 查询，不在本服务缓存房间归属。
	roomResp, err := h.roomQueryClient.GetMyRoom(request.Context(), &roomv1.GetMyRoomRequest{
		Meta:        httpkit.RoomMeta(request, "", ""),
		OwnerUserId: userID,
	})
	if err != nil {
		httpkit.WriteRPCError(writer, request, err)
		return
	}
	if roomResp.GetHasRoom() {
		roomData = roomTurnoverRewardRoomFromProto(roomResp.GetRoom(), userID)
	}

	// 区域必须使用 room-service 返回的可见区域快照，不能用请求 IP 或当前用户资料推断，否则房间迁区后会把进度查询到错误分桶。
	resp, err := h.roomTurnoverReward.GetRoomTurnoverRewardStatus(request.Context(), &activityv1.GetRoomTurnoverRewardStatusRequest{
		Meta:        httpkit.ActivityMeta(request),
		UserId:      userID,
		RegionId:    roomData.RegionID,
		RoomId:      roomData.RoomID,
		OwnerUserId: roomData.OwnerUserID,
	})
	if err != nil {
		httpkit.WriteRPCError(writer, request, err)
		return
	}

	userData := roomTurnoverRewardUserData{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 = roomTurnoverRewardUserFromProto(userResp.GetUsers()[userID], userID)
		}
	}

	httpkit.WriteOK(writer, request, roomTurnoverRewardStatusFromProto(resp.GetStatus(), roomData, userData))
}

func roomTurnoverRewardStatusFromProto(item *activityv1.RoomTurnoverRewardStatus, room roomTurnoverRewardRoomData, user roomTurnoverRewardUserData) roomTurnoverRewardStatusData {
	if item == nil {
		return roomTurnoverRewardStatusData{
			User:  user,
			Room:  room,
			Tiers: []roomTurnoverRewardTierData{},
		}
	}
	tiers := make([]roomTurnoverRewardTierData, 0, len(item.GetConfig().GetTiers()))
	for _, tier := range item.GetConfig().GetTiers() {
		tiers = append(tiers, roomTurnoverRewardTierFromProto(tier))
	}
	var matched *roomTurnoverRewardTierData
	if item.GetMatchedTier() != nil {
		// matched_tier 使用指针是为了区分“未达档位”和“达到了 ID 为 0 的空值”，前端可直接按 null 判断未命中。
		converted := roomTurnoverRewardTierFromProto(item.GetMatchedTier())
		matched = &converted
	}
	var latest *roomTurnoverRewardSettlementData
	if item.GetLatestSettlement() != nil {
		// latest_settlement 允许跨周期展示上一周发奖状态；当前周期流水清零后，H5 仍能提示最近一次结算结果。
		converted := roomTurnoverRewardSettlementFromProto(item.GetLatestSettlement())
		latest = &converted
	}
	room.RoomID = item.GetRoomId()
	room.OwnerUserID = item.GetOwnerUserId()
	if room.OwnerUserID == 0 {
		// 没有房间或 activity-service 未返回 owner 时，保留当前登录用户作为展示兜底，避免 H5 出现空 owner。
		room.OwnerUserID = user.UserID
	}
	return roomTurnoverRewardStatusData{
		Enabled: item.GetConfig().GetEnabled(),
		User:    user,
		Room:    room,
		Period: roomTurnoverRewardPeriodData{
			StartMS: item.GetPeriodStartMs(),
			EndMS:   item.GetPeriodEndMs(),
		},
		Tiers:                    tiers,
		CurrentCoinSpent:         item.GetCurrentCoinSpent(),
		ExpectedRewardCoinAmount: item.GetExpectedRewardCoinAmount(),
		MatchedTier:              matched,
		LatestSettlement:         latest,
		ServerTimeMS:             item.GetServerTimeMs(),
	}
}

func roomTurnoverRewardRoomFromProto(item *roomv1.RoomListItem, fallbackOwnerUserID int64) roomTurnoverRewardRoomData {
	if item == nil {
		return roomTurnoverRewardRoomData{OwnerUserID: fallbackOwnerUserID}
	}
	ownerID := item.GetOwnerUserId()
	if ownerID == 0 {
		ownerID = fallbackOwnerUserID
	}
	return roomTurnoverRewardRoomData{
		HasRoom:     true,
		RoomID:      item.GetRoomId(),
		OwnerUserID: ownerID,
		RegionID:    item.GetVisibleRegionId(),
		Title:       item.GetTitle(),
		CoverURL:    item.GetCoverUrl(),
	}
}

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

func roomTurnoverRewardTierFromProto(item *activityv1.RoomTurnoverRewardTier) roomTurnoverRewardTierData {
	if item == nil {
		return roomTurnoverRewardTierData{}
	}
	return roomTurnoverRewardTierData{
		TierID:             item.GetTierId(),
		TierCode:           item.GetTierCode(),
		TierName:           item.GetTierName(),
		ThresholdCoinSpent: item.GetThresholdCoinSpent(),
		RewardCoinAmount:   item.GetRewardCoinAmount(),
		Status:             item.GetStatus(),
		SortOrder:          item.GetSortOrder(),
	}
}

func roomTurnoverRewardSettlementFromProto(item *activityv1.RoomTurnoverRewardSettlement) roomTurnoverRewardSettlementData {
	if item == nil {
		return roomTurnoverRewardSettlementData{}
	}
	return roomTurnoverRewardSettlementData{
		SettlementID:        item.GetSettlementId(),
		RegionID:            item.GetRegionId(),
		RoomID:              item.GetRoomId(),
		OwnerUserID:         item.GetOwnerUserId(),
		PeriodStartMS:       item.GetPeriodStartMs(),
		PeriodEndMS:         item.GetPeriodEndMs(),
		CoinSpent:           item.GetCoinSpent(),
		TierID:              item.GetTierId(),
		TierCode:            item.GetTierCode(),
		ThresholdCoinSpent:  item.GetThresholdCoinSpent(),
		RewardCoinAmount:    item.GetRewardCoinAmount(),
		Status:              item.GetStatus(),
		WalletCommandID:     item.GetWalletCommandId(),
		WalletTransactionID: item.GetWalletTransactionId(),
		FailureReason:       item.GetFailureReason(),
		SettledAtMS:         item.GetSettledAtMs(),
		CreatedAtMS:         item.GetCreatedAtMs(),
		UpdatedAtMS:         item.GetUpdatedAtMs(),
	}
}
