package roomadmin

import (
	"context"
	"fmt"
	"strconv"
	"strings"

	"hyapp-admin-server/internal/integration/robotclient"
	"hyapp-admin-server/internal/integration/roomclient"
	"hyapp-admin-server/internal/modules/shared"
)

const availableRoomRobotPageSize = int32(200)

type RobotRoom struct {
	AppCode          string        `json:"appCode"`
	RoomID           string        `json:"roomId"`
	RoomShortID      string        `json:"roomShortId"`
	Title            string        `json:"title"`
	CoverURL         string        `json:"coverUrl"`
	VisibleRegionID  int64         `json:"visibleRegionId"`
	RegionName       string        `json:"regionName"`
	Status           string        `json:"status"`
	OwnerRobotUserID string        `json:"ownerRobotUserId"`
	Owner            RoomOwner     `json:"owner"`
	RobotUserIDs     []string      `json:"robotUserIds"`
	Robots           []RoomOwner   `json:"robots"`
	ActiveRobotCount int32         `json:"activeRobotCount"`
	SeatCount        int32         `json:"seatCount"`
	GiftRule         RobotGiftRule `json:"giftRule"`
	CreatedByAdminID uint64        `json:"createdByAdminId"`
	CreatedAtMS      int64         `json:"createdAtMs"`
	UpdatedAtMS      int64         `json:"updatedAtMs"`
}

type RobotGiftRule struct {
	GiftIDs              []string `json:"giftIds"`
	LuckyGiftIDs         []string `json:"luckyGiftIds"`
	NormalGiftIntervalMS int64    `json:"normalGiftIntervalMs"`
	LuckyComboMin        int64    `json:"luckyComboMin"`
	LuckyComboMax        int64    `json:"luckyComboMax"`
	LuckyPauseMinMS      int64    `json:"luckyPauseMinMs"`
	LuckyPauseMaxMS      int64    `json:"luckyPauseMaxMs"`
	RobotStayMinMS       int64    `json:"robotStayMinMs"`
	RobotStayMaxMS       int64    `json:"robotStayMaxMs"`
	RobotReplaceMinMS    int64    `json:"robotReplaceMinMs"`
	RobotReplaceMaxMS    int64    `json:"robotReplaceMaxMs"`
	MaxGiftSenders       int64    `json:"maxGiftSenders"`
}

type AvailableRoomRobot struct {
	UserID       string    `json:"userId"`
	Status       string    `json:"status"`
	RoomScene    string    `json:"roomScene"`
	LastUsedAtMS int64     `json:"lastUsedAtMs"`
	UsedCount    int64     `json:"usedCount"`
	User         RoomOwner `json:"user"`
}

type HumanRoomRobotConfig struct {
	AppCode                 string                      `json:"appCode"`
	Enabled                 bool                        `json:"enabled"`
	CandidateRoomMaxOnline  int32                       `json:"candidateRoomMaxOnline"`
	RoomFullStopOnline      int32                       `json:"roomFullStopOnline"`
	RoomTargetMinOnline     int32                       `json:"roomTargetMinOnline"`
	RoomTargetMaxOnline     int32                       `json:"roomTargetMaxOnline"`
	RobotStayMinMS          int64                       `json:"robotStayMinMs"`
	RobotStayMaxMS          int64                       `json:"robotStayMaxMs"`
	RobotReplaceMinMS       int64                       `json:"robotReplaceMinMs"`
	RobotReplaceMaxMS       int64                       `json:"robotReplaceMaxMs"`
	NormalGiftIntervalMS    int64                       `json:"normalGiftIntervalMs"`
	NormalGiftIntervalMinMS int64                       `json:"normalGiftIntervalMinMs"`
	NormalGiftIntervalMaxMS int64                       `json:"normalGiftIntervalMaxMs"`
	GiftIDs                 []string                    `json:"giftIds"`
	LuckyGiftIDs            []string                    `json:"luckyGiftIds"`
	SuperLuckyGiftIDs       []string                    `json:"superLuckyGiftIds"`
	LuckyComboMin           int64                       `json:"luckyComboMin"`
	LuckyComboMax           int64                       `json:"luckyComboMax"`
	LuckyPauseMinMS         int64                       `json:"luckyPauseMinMs"`
	LuckyPauseMaxMS         int64                       `json:"luckyPauseMaxMs"`
	MaxGiftSenders          int64                       `json:"maxGiftSenders"`
	AllowedOwnerIDs         []string                    `json:"allowedOwnerIds"`
	CountryLimitEnabled     bool                        `json:"countryLimitEnabled"`
	CountryRules            []HumanRoomRobotCountryRule `json:"countryRules"`
	UpdatedByAdminID        uint64                      `json:"updatedByAdminId"`
	CreatedAtMS             int64                       `json:"createdAtMs"`
	UpdatedAtMS             int64                       `json:"updatedAtMs"`
}

type HumanRoomRobotCountryRule struct {
	CountryCode     string                  `json:"countryCode"`
	MaxRoomCount    int32                   `json:"maxRoomCount"`
	AllowedOwnerIDs flexibleCommaStringList `json:"allowedOwnerIds"`
}

func (s *Service) ListRobotRooms(ctx context.Context, query robotRoomListQuery) ([]RobotRoom, int64, error) {
	if s.roomClient == nil {
		return nil, 0, fmt.Errorf("room service client is not configured")
	}
	if query.Page <= 0 {
		query.Page = 1
	}
	if query.PageSize <= 0 || query.PageSize > 100 {
		query.PageSize = 50
	}
	result, err := s.roomClient.ListRobotRooms(ctx, roomclient.ListRobotRoomsRequest{
		Page:     query.Page,
		PageSize: query.PageSize,
		Status:   normalizeRobotRoomListStatus(query.Status),
	})
	if err != nil {
		return nil, 0, err
	}
	items := robotRoomsFromClient(result.Rooms)
	if err := s.fillRobotRoomDetails(ctx, items); err != nil {
		return nil, 0, err
	}
	return items, result.Total, nil
}

func normalizeRobotRoomListStatus(status string) string {
	switch strings.TrimSpace(status) {
	case "active", "stopped":
		return strings.TrimSpace(status)
	default:
		return ""
	}
}

func (s *Service) ListAvailableRoomRobots(ctx context.Context) ([]AvailableRoomRobot, error) {
	if s.robotClient == nil || s.roomClient == nil {
		return nil, fmt.Errorf("robot or room service client is not configured")
	}
	robots, err := listAllActiveGameRobots(ctx, s.robotClient)
	if err != nil {
		return nil, err
	}
	userIDs := make([]int64, 0, len(robots))
	for _, item := range robots {
		if item.UserID > 0 {
			userIDs = append(userIDs, item.UserID)
		}
	}
	// 全站机器人是后台统一维护的机器人账号池；房间机器人下拉只把这批账号交给 room-service 做占用过滤，
	// 避免新增了全站机器人却因为旧的 room-scene 专用池为空而无法选择房主机器人。
	available, err := s.roomClient.FilterAvailableRoomRobots(ctx, userIDs)
	if err != nil {
		return nil, err
	}
	owners, err := s.queryRoomOwners(ctx, available.AvailableUserIDs)
	if err != nil {
		return nil, err
	}
	return availableRoomRobotsFromGamePool(robots, available.AvailableUserIDs, owners), nil
}

func listAllActiveGameRobots(ctx context.Context, client robotclient.Client) ([]robotclient.Robot, error) {
	if client == nil {
		return nil, fmt.Errorf("robot service client is not configured")
	}
	cursor := ""
	seenCursors := make(map[string]bool)
	robots := make([]robotclient.Robot, 0, availableRoomRobotPageSize)
	for {
		// 机器人房间下拉要先拿到完整全站 active 机器人池，再统一交给 room-service 做占用过滤；
		// 只取第一页会在测试服机器人数量超过 200 或第一页大多已占用时，把后续地区的新机器人挡在下拉外。
		result, err := client.ListGameRobots(ctx, robotclient.ListGameRobotsRequest{
			Status:   "active",
			PageSize: availableRoomRobotPageSize,
			Cursor:   cursor,
		})
		if err != nil {
			return nil, err
		}
		robots = append(robots, result.Robots...)
		next := strings.TrimSpace(result.NextCursor)
		if next == "" {
			return robots, nil
		}
		if seenCursors[next] {
			return nil, fmt.Errorf("robot service returned repeated cursor %q", next)
		}
		seenCursors[next] = true
		cursor = next
	}
}

func (s *Service) GetHumanRoomRobotConfig(ctx context.Context) (HumanRoomRobotConfig, error) {
	if s.roomClient == nil {
		return HumanRoomRobotConfig{}, fmt.Errorf("room service client is not configured")
	}
	config, err := s.roomClient.GetHumanRoomRobotConfig(ctx)
	if err != nil {
		return HumanRoomRobotConfig{}, err
	}
	return s.humanRoomRobotConfigFromClient(ctx, config)
}

func (s *Service) UpdateHumanRoomRobotConfig(ctx context.Context, req updateHumanRoomRobotConfigRequest, actor shared.Actor) (HumanRoomRobotConfig, error) {
	if s.roomClient == nil {
		return HumanRoomRobotConfig{}, fmt.Errorf("room service client is not configured")
	}
	config := roomclient.HumanRoomRobotConfig{
		Enabled:                 req.Enabled,
		CandidateRoomMaxOnline:  req.CandidateRoomMaxOnline,
		RoomFullStopOnline:      req.RoomFullStopOnline,
		RoomTargetMinOnline:     req.RoomTargetMinOnline,
		RoomTargetMaxOnline:     req.RoomTargetMaxOnline,
		RobotStayMinMS:          req.RobotStayMinMS,
		RobotStayMaxMS:          req.RobotStayMaxMS,
		RobotReplaceMinMS:       req.RobotReplaceMinMS,
		RobotReplaceMaxMS:       req.RobotReplaceMaxMS,
		NormalGiftIntervalMS:    req.NormalGiftIntervalMS,
		NormalGiftIntervalMinMS: req.NormalGiftIntervalMinMS,
		NormalGiftIntervalMaxMS: req.NormalGiftIntervalMaxMS,
		GiftIDs:                 normalizeStringList(req.GiftIDs),
		LuckyGiftIDs:            normalizeStringList(req.LuckyGiftIDs),
		SuperLuckyGiftIDs:       normalizeStringList(req.SuperLuckyGiftIDs),
		LuckyComboMin:           req.LuckyComboMin,
		LuckyComboMax:           req.LuckyComboMax,
		LuckyPauseMinMS:         req.LuckyPauseMinMS,
		LuckyPauseMaxMS:         req.LuckyPauseMaxMS,
		MaxGiftSenders:          req.MaxGiftSenders,
		AllowedOwnerIDs:         normalizeStringList([]string(req.AllowedOwnerIDs)),
		CountryLimitEnabled:     req.CountryLimitEnabled,
		CountryRules:            humanRoomRobotCountryRulesToClient(req.CountryRules),
	}
	saved, err := s.roomClient.UpdateHumanRoomRobotConfig(ctx, roomclient.UpdateHumanRoomRobotConfigRequest{
		Config:  config,
		AdminID: uint64(actor.UserID),
	})
	if err != nil {
		return HumanRoomRobotConfig{}, mapRoomClientError(err)
	}
	return s.humanRoomRobotConfigFromClient(ctx, saved)
}

func availableRoomRobotsFromGamePool(robots []robotclient.Robot, availableUserIDs []int64, owners map[int64]RoomOwner) []AvailableRoomRobot {
	allowed := make(map[int64]bool, len(availableUserIDs))
	for _, userID := range availableUserIDs {
		allowed[userID] = true
	}
	items := make([]AvailableRoomRobot, 0, len(availableUserIDs))
	for _, robot := range robots {
		if !allowed[robot.UserID] {
			continue
		}
		items = append(items, AvailableRoomRobot{
			UserID:       strconv.FormatInt(robot.UserID, 10),
			Status:       robot.Status,
			RoomScene:    robot.RoomScene,
			LastUsedAtMS: robot.LastUsedAtMS,
			UsedCount:    robot.UsedCount,
			User:         owners[robot.UserID],
		})
	}
	return items
}

func normalizeStringList(values []string) []string {
	seen := make(map[string]bool, len(values))
	out := make([]string, 0, len(values))
	for _, value := range values {
		value = strings.TrimSpace(value)
		if value == "" || seen[value] {
			continue
		}
		seen[value] = true
		out = append(out, value)
	}
	return out
}

func (s *Service) humanRoomRobotConfigFromClient(_ context.Context, config roomclient.HumanRoomRobotConfig) (HumanRoomRobotConfig, error) {
	out := HumanRoomRobotConfig{
		AppCode:                 config.AppCode,
		Enabled:                 config.Enabled,
		CandidateRoomMaxOnline:  config.CandidateRoomMaxOnline,
		RoomFullStopOnline:      config.RoomFullStopOnline,
		RoomTargetMinOnline:     config.RoomTargetMinOnline,
		RoomTargetMaxOnline:     config.RoomTargetMaxOnline,
		RobotStayMinMS:          config.RobotStayMinMS,
		RobotStayMaxMS:          config.RobotStayMaxMS,
		RobotReplaceMinMS:       config.RobotReplaceMinMS,
		RobotReplaceMaxMS:       config.RobotReplaceMaxMS,
		NormalGiftIntervalMS:    config.NormalGiftIntervalMS,
		NormalGiftIntervalMinMS: config.NormalGiftIntervalMinMS,
		NormalGiftIntervalMaxMS: config.NormalGiftIntervalMaxMS,
		GiftIDs:                 append([]string(nil), config.GiftIDs...),
		LuckyGiftIDs:            append([]string(nil), config.LuckyGiftIDs...),
		SuperLuckyGiftIDs:       append([]string(nil), config.SuperLuckyGiftIDs...),
		LuckyComboMin:           config.LuckyComboMin,
		LuckyComboMax:           config.LuckyComboMax,
		LuckyPauseMinMS:         config.LuckyPauseMinMS,
		LuckyPauseMaxMS:         config.LuckyPauseMaxMS,
		MaxGiftSenders:          config.MaxGiftSenders,
		AllowedOwnerIDs:         append([]string(nil), config.AllowedOwnerIDs...),
		CountryLimitEnabled:     config.CountryLimitEnabled,
		CountryRules:            humanRoomRobotCountryRulesFromClient(config.CountryRules),
		UpdatedByAdminID:        config.UpdatedByAdminID,
		CreatedAtMS:             config.CreatedAtMS,
		UpdatedAtMS:             config.UpdatedAtMS,
	}
	return out, nil
}

func humanRoomRobotCountryRulesToClient(values []HumanRoomRobotCountryRule) []roomclient.HumanRoomRobotCountryRule {
	out := make([]roomclient.HumanRoomRobotCountryRule, 0, len(values))
	for _, value := range values {
		out = append(out, roomclient.HumanRoomRobotCountryRule{
			CountryCode:     strings.ToUpper(strings.TrimSpace(value.CountryCode)),
			MaxRoomCount:    value.MaxRoomCount,
			AllowedOwnerIDs: normalizeStringList([]string(value.AllowedOwnerIDs)),
		})
	}
	return out
}

func humanRoomRobotCountryRulesFromClient(values []roomclient.HumanRoomRobotCountryRule) []HumanRoomRobotCountryRule {
	out := make([]HumanRoomRobotCountryRule, 0, len(values))
	for _, value := range values {
		out = append(out, HumanRoomRobotCountryRule{
			CountryCode:     value.CountryCode,
			MaxRoomCount:    value.MaxRoomCount,
			AllowedOwnerIDs: flexibleCommaStringList(append([]string(nil), value.AllowedOwnerIDs...)),
		})
	}
	return out
}

func (s *Service) CreateRobotRoom(ctx context.Context, req createRobotRoomRequest, actor shared.Actor) (RobotRoom, error) {
	if s.roomClient == nil {
		return RobotRoom{}, fmt.Errorf("room service client is not configured")
	}
	normalized, err := normalizeCreateRobotRoomRequest(req)
	if err != nil {
		return RobotRoom{}, err
	}
	req = normalized
	if err := s.applyOwnerProfileToRobotRoomRequest(ctx, &req); err != nil {
		return RobotRoom{}, err
	}
	created, err := s.roomClient.CreateRobotRoom(ctx, roomclient.CreateRobotRoomRequest{
		OwnerRobotUserID:      int64(req.OwnerRobotUserID),
		CandidateRobotUserIDs: []int64(req.CandidateRobotUserIDs),
		MinRobotCount:         req.MinRobotCount,
		MaxRobotCount:         req.MaxRobotCount,
		RoomName:              req.RoomName,
		RoomAvatar:            req.RoomAvatar,
		VisibleRegionID:       req.VisibleRegionID,
		OwnerCountryCode:      req.OwnerCountryCode,
		SeatCount:             req.SeatCount,
		GiftRule: roomclient.RobotRoomGiftRule{
			GiftIDs:              req.GiftIDs,
			LuckyGiftIDs:         req.LuckyGiftIDs,
			NormalGiftIntervalMS: req.NormalGiftIntervalMS,
			LuckyComboMin:        req.LuckyComboMin,
			LuckyComboMax:        req.LuckyComboMax,
			LuckyPauseMinMS:      req.LuckyPauseMinMS,
			LuckyPauseMaxMS:      req.LuckyPauseMaxMS,
			RobotStayMinMS:       req.RobotStayMinMS,
			RobotStayMaxMS:       req.RobotStayMaxMS,
			RobotReplaceMinMS:    req.RobotReplaceMinMS,
			RobotReplaceMaxMS:    req.RobotReplaceMaxMS,
			MaxGiftSenders:       req.MaxGiftSenders,
		},
		AdminID: uint64(actor.UserID),
	})
	if err != nil {
		return RobotRoom{}, mapRoomClientError(err)
	}
	items := []RobotRoom{robotRoomFromClient(created)}
	if err := s.fillRobotRoomDetails(ctx, items); err != nil {
		return RobotRoom{}, err
	}
	return items[0], nil
}

func (s *Service) applyOwnerProfileToRobotRoomRequest(ctx context.Context, req *createRobotRoomRequest) error {
	if s.userDB == nil {
		return fmt.Errorf("user database is not configured")
	}
	ownerID := int64(req.OwnerRobotUserID)
	owners, err := s.queryRoomOwners(ctx, []int64{ownerID})
	if err != nil {
		return err
	}
	owner, ok := owners[ownerID]
	if !ok {
		return fmt.Errorf("%w: 房主机器人资料不存在", ErrInvalidArgument)
	}
	return applyOwnerProfileToRobotRoomRequest(req, owner)
}

func applyOwnerProfileToRobotRoomRequest(req *createRobotRoomRequest, owner RoomOwner) error {
	roomName, roomAvatar, err := robotRoomProfileFromOwner(owner)
	if err != nil {
		return err
	}
	// 机器人房间对外展示和区域归属必须跟随房主机器人资料，避免后台表单或脚本传入的自定义值让房间卡片、区域桶和国家筛选不一致。
	req.RoomName = roomName
	req.RoomAvatar = roomAvatar
	req.VisibleRegionID = owner.VisibleRegionID
	req.OwnerCountryCode = strings.ToUpper(strings.TrimSpace(owner.CountryCode))
	return nil
}

func robotRoomProfileFromOwner(owner RoomOwner) (string, string, error) {
	name := strings.TrimSpace(owner.Username)
	avatar := strings.TrimSpace(owner.Avatar)
	if name == "" {
		return "", "", fmt.Errorf("%w: 房主机器人名称不能为空", ErrInvalidArgument)
	}
	if avatar == "" {
		return "", "", fmt.Errorf("%w: 房主机器人头像不能为空", ErrInvalidArgument)
	}
	return name, avatar, nil
}

func (s *Service) SetRobotRoomStatus(ctx context.Context, roomID string, status string, actor shared.Actor) (RobotRoom, error) {
	if s.roomClient == nil {
		return RobotRoom{}, fmt.Errorf("room service client is not configured")
	}
	roomID = strings.TrimSpace(roomID)
	status = strings.TrimSpace(status)
	if roomID == "" || (status != "active" && status != "stopped") {
		return RobotRoom{}, fmt.Errorf("%w: 机器人房间状态参数不正确", ErrInvalidArgument)
	}
	item, err := s.roomClient.SetRobotRoomStatus(ctx, roomclient.SetRobotRoomStatusRequest{
		RoomID:  roomID,
		Status:  status,
		AdminID: uint64(actor.UserID),
	})
	if err != nil {
		return RobotRoom{}, mapRoomClientError(err)
	}
	items := []RobotRoom{robotRoomFromClient(item)}
	if err := s.fillRobotRoomDetails(ctx, items); err != nil {
		return RobotRoom{}, err
	}
	return items[0], nil
}

func normalizeCreateRobotRoomRequest(req createRobotRoomRequest) (createRobotRoomRequest, error) {
	ownerID := int64(req.OwnerRobotUserID)
	if ownerID <= 0 {
		return req, fmt.Errorf("%w: 请选择房主机器人", ErrInvalidArgument)
	}
	if req.MinRobotCount <= 0 || req.MaxRobotCount < req.MinRobotCount {
		return req, fmt.Errorf("%w: 机器人数量范围不正确", ErrInvalidArgument)
	}
	if req.SeatCount <= 0 {
		req.SeatCount = 10
	}
	if !validRobotRoomSeatCount(req.SeatCount) {
		return req, fmt.Errorf("%w: 麦位数不正确", ErrInvalidArgument)
	}
	candidateIDs := normalizeRobotRoomCandidateIDs([]int64(req.CandidateRobotUserIDs), ownerID)
	if len(candidateIDs) == 0 {
		return req, fmt.Errorf("%w: 请选择候选机器人", ErrInvalidArgument)
	}
	if len(req.GiftIDs) == 0 {
		return req, fmt.Errorf("%w: 请选择普通礼物合集", ErrInvalidArgument)
	}
	if len(req.LuckyGiftIDs) == 0 {
		return req, fmt.Errorf("%w: 请选择幸运礼物合集", ErrInvalidArgument)
	}
	if req.NormalGiftIntervalMS <= 0 {
		return req, fmt.Errorf("%w: 普通礼物频次不正确", ErrInvalidArgument)
	}
	if req.LuckyComboMin <= 0 || req.LuckyComboMax < req.LuckyComboMin {
		return req, fmt.Errorf("%w: 幸运礼物连击范围不正确", ErrInvalidArgument)
	}
	if req.LuckyPauseMinMS <= 0 || req.LuckyPauseMaxMS < req.LuckyPauseMinMS {
		return req, fmt.Errorf("%w: 幸运礼物间隔范围不正确", ErrInvalidArgument)
	}
	if req.RobotStayMinMS < 0 || req.RobotStayMaxMS < req.RobotStayMinMS {
		return req, fmt.Errorf("%w: 机器人停留时间范围不正确", ErrInvalidArgument)
	}
	if req.RobotReplaceMinMS < 0 || req.RobotReplaceMaxMS < req.RobotReplaceMinMS {
		return req, fmt.Errorf("%w: 机器人补位时间范围不正确", ErrInvalidArgument)
	}
	if req.MaxGiftSenders < 0 {
		return req, fmt.Errorf("%w: 同时送礼机器人数量不正确", ErrInvalidArgument)
	}
	req.CandidateRobotUserIDs = flexibleJSONInt64Slice(candidateIDs)
	return req, nil
}

func validRobotRoomSeatCount(seatCount int32) bool {
	switch seatCount {
	case 10, 15, 20:
		return true
	default:
		return false
	}
}

func normalizeRobotRoomCandidateIDs(values []int64, ownerID int64) []int64 {
	seen := make(map[int64]bool, len(values))
	out := make([]int64, 0, len(values))
	for _, value := range values {
		// 房主由 room-service 单独并入机器人集合；候选列表只保留其他机器人，避免前端重复选择或旧脚本传入重复 ID。
		if value <= 0 || value == ownerID || seen[value] {
			continue
		}
		seen[value] = true
		out = append(out, value)
	}
	return out
}

func robotRoomsFromClient(items []roomclient.RobotRoom) []RobotRoom {
	out := make([]RobotRoom, 0, len(items))
	for _, item := range items {
		out = append(out, robotRoomFromClient(item))
	}
	return out
}

func robotRoomFromClient(item roomclient.RobotRoom) RobotRoom {
	robotUserIDs := make([]string, 0, len(item.RobotUserIDs))
	for _, userID := range item.RobotUserIDs {
		robotUserIDs = append(robotUserIDs, strconv.FormatInt(userID, 10))
	}
	return RobotRoom{
		AppCode:          item.AppCode,
		RoomID:           item.RoomID,
		RoomShortID:      item.RoomShortID,
		Title:            item.Title,
		CoverURL:         item.CoverURL,
		VisibleRegionID:  item.VisibleRegionID,
		Status:           item.Status,
		OwnerRobotUserID: strconv.FormatInt(item.OwnerRobotUserID, 10),
		RobotUserIDs:     robotUserIDs,
		ActiveRobotCount: item.ActiveRobotCount,
		SeatCount:        item.SeatCount,
		GiftRule: RobotGiftRule{
			GiftIDs:              item.GiftRule.GiftIDs,
			LuckyGiftIDs:         item.GiftRule.LuckyGiftIDs,
			NormalGiftIntervalMS: item.GiftRule.NormalGiftIntervalMS,
			LuckyComboMin:        item.GiftRule.LuckyComboMin,
			LuckyComboMax:        item.GiftRule.LuckyComboMax,
			LuckyPauseMinMS:      item.GiftRule.LuckyPauseMinMS,
			LuckyPauseMaxMS:      item.GiftRule.LuckyPauseMaxMS,
			RobotStayMinMS:       item.GiftRule.RobotStayMinMS,
			RobotStayMaxMS:       item.GiftRule.RobotStayMaxMS,
			RobotReplaceMinMS:    item.GiftRule.RobotReplaceMinMS,
			RobotReplaceMaxMS:    item.GiftRule.RobotReplaceMaxMS,
			MaxGiftSenders:       item.GiftRule.MaxGiftSenders,
		},
		CreatedByAdminID: item.CreatedByAdminID,
		CreatedAtMS:      item.CreatedAtMS,
		UpdatedAtMS:      item.UpdatedAtMS,
	}
}

func (s *Service) fillRobotRoomDetails(ctx context.Context, items []RobotRoom) error {
	if s.userDB == nil || len(items) == 0 {
		return nil
	}
	userIDs := make([]int64, 0)
	regionIDs := make([]int64, 0)
	for _, item := range items {
		if ownerID, err := strconv.ParseInt(item.OwnerRobotUserID, 10, 64); err == nil && ownerID > 0 {
			userIDs = append(userIDs, ownerID)
		}
		for _, rawID := range item.RobotUserIDs {
			if userID, err := strconv.ParseInt(rawID, 10, 64); err == nil && userID > 0 {
				userIDs = append(userIDs, userID)
			}
		}
		if item.VisibleRegionID > 0 {
			regionIDs = append(regionIDs, item.VisibleRegionID)
		}
	}
	owners, err := s.queryRoomOwners(ctx, uniqueInt64s(userIDs))
	if err != nil {
		return err
	}
	regions, err := s.queryRegionNames(ctx, uniqueInt64s(regionIDs))
	if err != nil {
		return err
	}
	for index := range items {
		if ownerID, err := strconv.ParseInt(items[index].OwnerRobotUserID, 10, 64); err == nil {
			items[index].Owner = owners[ownerID]
		}
		for _, rawID := range items[index].RobotUserIDs {
			if userID, err := strconv.ParseInt(rawID, 10, 64); err == nil {
				items[index].Robots = append(items[index].Robots, owners[userID])
			}
		}
		items[index].RegionName = regions[items[index].VisibleRegionID]
	}
	return nil
}
