package roomadmin

import (
	"encoding/json"
	"fmt"
	"strconv"
	"strings"

	"hyapp-admin-server/internal/modules/shared"
)

type listQuery struct {
	Page             int
	PageSize         int
	Keyword          string
	OwnerUserID      int64
	OwnerUserIDs     []int64
	OwnerUserKeyword string
	OwnerFilter      shared.UserIdentityFilter
	Status           string
	RegionID         int64
	SortBy           string
	SortDirection    string
}

type roomPinListQuery struct {
	Keyword  string
	Page     int
	PageSize int
	PinType  string
	RegionID int64
	Status   string
}

type robotRoomListQuery struct {
	Page     int
	PageSize int
	Status   string
}

type createRobotRoomRequest struct {
	OwnerRobotUserID      flexibleJSONInt64      `json:"ownerRobotUserId"`
	CandidateRobotUserIDs flexibleJSONInt64Slice `json:"candidateRobotUserIds"`
	MinRobotCount         int32                  `json:"minRobotCount"`
	MaxRobotCount         int32                  `json:"maxRobotCount"`
	RoomName              string                 `json:"roomName"`
	RoomAvatar            string                 `json:"roomAvatar"`
	VisibleRegionID       int64                  `json:"visibleRegionId"`
	OwnerCountryCode      string                 `json:"-"`
	SeatCount             int32                  `json:"seatCount"`
	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 flexibleJSONInt64 int64

type flexibleJSONInt64Slice []int64

func (v *flexibleJSONInt64) UnmarshalJSON(data []byte) error {
	// 机器人用户 ID 来自 int64，前端必须按字符串提交才能避开 JS 安全整数上限；这里同时兼容旧脚本传数字。
	value, err := parseFlexibleJSONInt64(data)
	if err != nil {
		return err
	}
	*v = flexibleJSONInt64(value)
	return nil
}

func (values *flexibleJSONInt64Slice) UnmarshalJSON(data []byte) error {
	// JSON 数组逐项走同一套 int64 解析，避免候选机器人列表里混入浮点或科学计数法。
	var raw []json.RawMessage
	if err := json.Unmarshal(data, &raw); err != nil {
		return err
	}
	out := make([]int64, 0, len(raw))
	for _, item := range raw {
		value, err := parseFlexibleJSONInt64(item)
		if err != nil {
			return err
		}
		out = append(out, value)
	}
	*values = out
	return nil
}

func parseFlexibleJSONInt64(data []byte) (int64, error) {
	raw := strings.TrimSpace(string(data))
	if raw == "" || raw == "null" {
		return 0, nil
	}
	if strings.HasPrefix(raw, "\"") {
		var text string
		if err := json.Unmarshal(data, &text); err != nil {
			return 0, err
		}
		raw = strings.TrimSpace(text)
	}
	if raw == "" {
		return 0, nil
	}
	if strings.ContainsAny(raw, ".eE") {
		// ID 没有小数语义，拒绝 float/scientific notation，避免 18 位 ID 被中间层改写精度。
		return 0, fmt.Errorf("integer id must not be decimal")
	}
	return strconv.ParseInt(raw, 10, 64)
}

type createRoomPinRequest struct {
	DurationDays int64  `json:"durationDays"`
	ExpiresAtMS  int64  `json:"expiresAtMs"`
	PinType      string `json:"pinType"`
	PinnedAtMS   int64  `json:"pinnedAtMs"`
	RoomID       string `json:"roomId"`
	Weight       int64  `json:"weight"`
}

type updateRoomRequest struct {
	CoverURL        *string `json:"coverUrl"`
	CloseReason     *string `json:"closeReason"`
	Description     *string `json:"description"`
	Mode            *string `json:"mode"`
	Status          *string `json:"status"`
	Title           *string `json:"title"`
	VisibleRegionID *int64  `json:"visibleRegionId"`
}

type moderateRoomRequest struct {
	Reason string `json:"reason"`
}

type updateRoomConfigRequest struct {
	AllowedSeatCounts []int32 `json:"allowedSeatCounts"`
	DefaultSeatCount  int32   `json:"defaultSeatCount"`
}

type updateRoomWhitelistRequest struct {
	UserIDs flexibleJSONInt64StringSlice `json:"userIds"`
}

type updateHumanRoomRobotConfigRequest struct {
	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         flexibleCommaStringList     `json:"allowedOwnerIds"`
	CountryLimitEnabled     bool                        `json:"countryLimitEnabled"`
	CountryRules            []HumanRoomRobotCountryRule `json:"countryRules"`
}

type flexibleJSONInt64StringSlice []string

func (values *flexibleJSONInt64StringSlice) UnmarshalJSON(data []byte) error {
	// 房间白名单 user_id 是 int64 标识，API 合约统一按字符串输出；这里兼容旧脚本传数字但拒绝小数。
	var raw []json.RawMessage
	if err := json.Unmarshal(data, &raw); err != nil {
		return err
	}
	out := make([]string, 0, len(raw))
	for _, item := range raw {
		value, err := parseFlexibleJSONInt64(item)
		if err != nil {
			return err
		}
		if value > 0 {
			out = append(out, strconv.FormatInt(value, 10))
		}
	}
	*values = out
	return nil
}

type flexibleCommaStringList []string

func (values *flexibleCommaStringList) UnmarshalJSON(data []byte) error {
	// 真人房机器人后台是人工输入框场景，兼容 "1001,1002" 和 ["1001","1002"] 两种提交，统一在 service 层去空去重。
	raw := strings.TrimSpace(string(data))
	if raw == "" || raw == "null" {
		*values = nil
		return nil
	}
	if strings.HasPrefix(raw, "\"") {
		var text string
		if err := json.Unmarshal(data, &text); err != nil {
			return err
		}
		*values = splitCommaStringList(text)
		return nil
	}
	var list []string
	if err := json.Unmarshal(data, &list); err != nil {
		return err
	}
	*values = splitCommaStringList(strings.Join(list, ","))
	return nil
}

func splitCommaStringList(raw string) []string {
	parts := strings.Split(raw, ",")
	out := make([]string, 0, len(parts))
	for _, part := range parts {
		part = strings.TrimSpace(part)
		if part != "" {
			out = append(out, part)
		}
	}
	return out
}
