package gamemanagement

import (
	"strconv"
	"strings"

	gamev1 "hyapp.local/api/proto/game/v1"
)

type platformDTO struct {
	AppCode      string `json:"appCode"`
	PlatformCode string `json:"platformCode"`
	PlatformName string `json:"platformName"`
	Status       string `json:"status"`
	APIBaseURL   string `json:"apiBaseUrl"`
	// adapterType 决定服务端按哪家厂商协议拼启动 URL 和处理回调。
	AdapterType string `json:"adapterType"`
	// callbackSecret 是后台配置页可见的厂商 key/AppSecret；只对有 game:view 权限的管理员返回。
	CallbackSecret      string   `json:"callbackSecret"`
	CallbackSecretSet   bool     `json:"callbackSecretSet"`
	CallbackIPWhitelist []string `json:"callbackIpWhitelist"`
	// adapterConfigJson 承载 uid_mode/default_lang/token_ttl_seconds 等可热更新配置。
	AdapterConfigJSON string `json:"adapterConfigJson"`
	SortOrder         int32  `json:"sortOrder"`
	CreatedAtMS       int64  `json:"createdAtMs"`
	UpdatedAtMS       int64  `json:"updatedAtMs"`
}

type catalogDTO struct {
	AppCode        string `json:"appCode"`
	GameID         string `json:"gameId"`
	PlatformCode   string `json:"platformCode"`
	ProviderGameID string `json:"providerGameId"`
	GameName       string `json:"gameName"`
	Category       string `json:"category"`
	IconURL        string `json:"iconUrl"`
	CoverURL       string `json:"coverUrl"`
	// launchUrl 只在厂商列表预览时返回，正式目录仍由 platform.adapterConfigJson.game_urls 按 providerGameId 解析。
	LaunchURL   string   `json:"launchUrl,omitempty"`
	LaunchMode  string   `json:"launchMode"`
	Orientation string   `json:"orientation"`
	SafeHeight  int32    `json:"safeHeight"`
	MinCoin     int64    `json:"minCoin"`
	Status      string   `json:"status"`
	SortOrder   int32    `json:"sortOrder"`
	Tags        []string `json:"tags"`
	CreatedAtMS int64    `json:"createdAtMs"`
	UpdatedAtMS int64    `json:"updatedAtMs"`
	// whitelistEnabled 只表示访问策略是否生效；成员通过独立接口按需加载，避免目录列表膨胀。
	WhitelistEnabled bool `json:"whitelistEnabled"`
}

type diceConfigDTO struct {
	AppCode          string         `json:"appCode"`
	GameID           string         `json:"gameId"`
	Status           string         `json:"status"`
	StakeOptions     []diceStakeDTO `json:"stakeOptions"`
	FeeBPS           int32          `json:"feeBps"`
	PoolBPS          int32          `json:"poolBps"`
	MinPlayers       int32          `json:"minPlayers"`
	MaxPlayers       int32          `json:"maxPlayers"`
	RobotEnabled     bool           `json:"robotEnabled"`
	RobotMatchWaitMS int64          `json:"robotMatchWaitMs"`
	PoolBalanceCoin  int64          `json:"poolBalanceCoin"`
	CreatedAtMS      int64          `json:"createdAtMs"`
	UpdatedAtMS      int64          `json:"updatedAtMs"`
}

type diceStakeDTO struct {
	StakeCoin int64 `json:"stakeCoin"`
	Enabled   bool  `json:"enabled"`
	SortOrder int32 `json:"sortOrder"`
}

type dicePoolAdjustmentDTO struct {
	AdjustmentID string `json:"adjustmentId"`
	GameID       string `json:"gameId"`
	StakeCoin    int64  `json:"stakeCoin"`
	AmountCoin   int64  `json:"amountCoin"`
	Direction    string `json:"direction"`
	Reason       string `json:"reason"`
	BalanceAfter int64  `json:"balanceAfter"`
	CreatedAtMS  int64  `json:"createdAtMs"`
}

type selfGameStakePoolDTO struct {
	AppCode            string `json:"appCode"`
	GameID             string `json:"gameId"`
	StakeCoin          int64  `json:"stakeCoin"`
	BalanceCoin        int64  `json:"balanceCoin"`
	ReservedCoin       int64  `json:"reservedCoin"`
	AvailableCoin      int64  `json:"availableCoin"`
	TargetBalanceCoin  int64  `json:"targetBalanceCoin"`
	SafeBalanceCoin    int64  `json:"safeBalanceCoin"`
	WarningBalanceCoin int64  `json:"warningBalanceCoin"`
	DangerBalanceCoin  int64  `json:"dangerBalanceCoin"`
	Status             string `json:"status"`
	PoolLevel          string `json:"poolLevel"`
	RequiredPoolCoin   int64  `json:"requiredPoolCoin"`
	HumanWinCapacity   int64  `json:"humanWinCapacity"`
	BotMatchEnabled    bool   `json:"botMatchEnabled"`
	BlackReason        string `json:"blackReason"`
	CreatedAtMS        int64  `json:"createdAtMs"`
	UpdatedAtMS        int64  `json:"updatedAtMs"`
}

type selfGameNewUserPolicyDTO struct {
	AppCode                         string `json:"appCode"`
	GameID                          string `json:"gameId"`
	Enabled                         bool   `json:"enabled"`
	ProtectionRounds                int32  `json:"protectionRounds"`
	ProtectionHours                 int32  `json:"protectionHours"`
	MaxStakeCoin                    int64  `json:"maxStakeCoin"`
	LifetimeSubsidyQuotaCoin        int64  `json:"lifetimeSubsidyQuotaCoin"`
	Day1SubsidyQuotaCoin            int64  `json:"day1SubsidyQuotaCoin"`
	SingleRoundSubsidyCapCoin       int64  `json:"singleRoundSubsidyCapCoin"`
	StrategyLevel                   string `json:"strategyLevel"`
	LoseStreakProtectionEnabled     bool   `json:"loseStreakProtectionEnabled"`
	LoseStreakTrigger               int32  `json:"loseStreakTrigger"`
	NormalPhaseTargetWinRatePercent int32  `json:"normalPhaseTargetWinRatePercent"`
	BlackPoolRobotForceWinEnabled   bool   `json:"blackPoolRobotForceWinEnabled"`
	CreatedAtMS                     int64  `json:"createdAtMs"`
	UpdatedAtMS                     int64  `json:"updatedAtMs"`
}

type diceRobotDTO struct {
	AppCode          string `json:"appCode"`
	GameID           string `json:"gameId"`
	UserID           string `json:"userId"`
	UserIDNumber     int64  `json:"userIdNumber"`
	ShortID          string `json:"shortId"`
	Nickname         string `json:"nickname"`
	Avatar           string `json:"avatar"`
	Status           string `json:"status"`
	CreatedByAdminID int64  `json:"createdByAdminId"`
	CreatedAtMS      int64  `json:"createdAtMs"`
	UpdatedAtMS      int64  `json:"updatedAtMs"`
}

type roomRPSConfigDTO struct {
	AppCode            string                `json:"appCode"`
	GameID             string                `json:"gameId"`
	Status             string                `json:"status"`
	ChallengeTimeoutMS int64                 `json:"challengeTimeoutMs"`
	RevealCountdownMS  int64                 `json:"revealCountdownMs"`
	StakeGifts         []roomRPSStakeGiftDTO `json:"stakeGifts"`
	CreatedAtMS        int64                 `json:"createdAtMs"`
	UpdatedAtMS        int64                 `json:"updatedAtMs"`
}

type roomRPSStakeGiftDTO struct {
	GiftID           string `json:"giftId"`
	GiftIDNumber     int64  `json:"giftIdNumber"`
	GiftName         string `json:"giftName"`
	GiftIconURL      string `json:"giftIconUrl"`
	GiftAnimationURL string `json:"giftAnimationUrl"`
	GiftPriceCoin    int64  `json:"giftPriceCoin"`
	Enabled          bool   `json:"enabled"`
	SortOrder        int32  `json:"sortOrder"`
}

type roomRPSChallengeDTO struct {
	AppCode            string           `json:"appCode"`
	ChallengeID        string           `json:"challengeId"`
	RoomID             string           `json:"roomId"`
	RegionID           int64            `json:"regionId"`
	Status             string           `json:"status"`
	StakeGiftID        string           `json:"stakeGiftId"`
	StakeGiftIDNumber  int64            `json:"stakeGiftIdNumber"`
	StakeCoin          int64            `json:"stakeCoin"`
	Initiator          roomRPSPlayerDTO `json:"initiator"`
	Challenger         roomRPSPlayerDTO `json:"challenger"`
	WinnerUserID       string           `json:"winnerUserId"`
	WinnerUserIDNumber int64            `json:"winnerUserIdNumber"`
	SettlementStatus   string           `json:"settlementStatus"`
	FailureReason      string           `json:"failureReason"`
	TimeoutAtMS        int64            `json:"timeoutAtMs"`
	RevealAtMS         int64            `json:"revealAtMs"`
	CreatedAtMS        int64            `json:"createdAtMs"`
	MatchedAtMS        int64            `json:"matchedAtMs"`
	SettledAtMS        int64            `json:"settledAtMs"`
	UpdatedAtMS        int64            `json:"updatedAtMs"`
}

type roomRPSPlayerDTO struct {
	UserID       string `json:"userId"`
	UserIDNumber int64  `json:"userIdNumber"`
	Gesture      string `json:"gesture"`
	Result       string `json:"result"`
	BalanceAfter int64  `json:"balanceAfter"`
	JoinedAtMS   int64  `json:"joinedAtMs"`
}

func platformFromProto(item *gamev1.GamePlatform) platformDTO {
	if item == nil {
		return platformDTO{}
	}
	return platformDTO{
		AppCode:             item.GetAppCode(),
		PlatformCode:        item.GetPlatformCode(),
		PlatformName:        item.GetPlatformName(),
		Status:              item.GetStatus(),
		APIBaseURL:          item.GetApiBaseUrl(),
		AdapterType:         item.GetAdapterType(),
		CallbackSecret:      item.GetCallbackSecret(),
		CallbackSecretSet:   item.GetCallbackSecretSet(),
		CallbackIPWhitelist: item.GetCallbackIpWhitelist(),
		AdapterConfigJSON:   item.GetAdapterConfigJson(),
		SortOrder:           item.GetSortOrder(),
		CreatedAtMS:         item.GetCreatedAtMs(),
		UpdatedAtMS:         item.GetUpdatedAtMs(),
	}
}

func catalogFromProto(item *gamev1.GameCatalogItem) catalogDTO {
	if item == nil {
		return catalogDTO{}
	}
	return catalogDTO{
		AppCode:          item.GetAppCode(),
		GameID:           item.GetGameId(),
		PlatformCode:     item.GetPlatformCode(),
		ProviderGameID:   item.GetProviderGameId(),
		GameName:         item.GetGameName(),
		Category:         item.GetCategory(),
		IconURL:          item.GetIconUrl(),
		CoverURL:         item.GetCoverUrl(),
		LaunchMode:       item.GetLaunchMode(),
		Orientation:      item.GetOrientation(),
		SafeHeight:       item.GetSafeHeight(),
		MinCoin:          item.GetMinCoin(),
		Status:           item.GetStatus(),
		SortOrder:        item.GetSortOrder(),
		Tags:             item.GetTags(),
		CreatedAtMS:      item.GetCreatedAtMs(),
		UpdatedAtMS:      item.GetUpdatedAtMs(),
		WhitelistEnabled: item.GetWhitelistEnabled(),
	}
}

func diceConfigFromProto(item *gamev1.DiceConfig) diceConfigDTO {
	if item == nil {
		return diceConfigDTO{}
	}
	options := make([]diceStakeDTO, 0, len(item.GetStakeOptions()))
	for _, option := range item.GetStakeOptions() {
		options = append(options, diceStakeDTO{
			StakeCoin: option.GetStakeCoin(),
			Enabled:   option.GetEnabled(),
			SortOrder: option.GetSortOrder(),
		})
	}
	return diceConfigDTO{
		AppCode:          item.GetAppCode(),
		GameID:           item.GetGameId(),
		Status:           item.GetStatus(),
		StakeOptions:     options,
		FeeBPS:           item.GetFeeBps(),
		PoolBPS:          item.GetPoolBps(),
		MinPlayers:       item.GetMinPlayers(),
		MaxPlayers:       item.GetMaxPlayers(),
		RobotEnabled:     item.GetRobotEnabled(),
		RobotMatchWaitMS: item.GetRobotMatchWaitMs(),
		PoolBalanceCoin:  item.GetPoolBalanceCoin(),
		CreatedAtMS:      item.GetCreatedAtMs(),
		UpdatedAtMS:      item.GetUpdatedAtMs(),
	}
}

func dicePoolAdjustmentFromProto(item *gamev1.DicePoolAdjustment) dicePoolAdjustmentDTO {
	if item == nil {
		return dicePoolAdjustmentDTO{}
	}
	return dicePoolAdjustmentDTO{
		AdjustmentID: item.GetAdjustmentId(),
		GameID:       item.GetGameId(),
		StakeCoin:    item.GetStakeCoin(),
		AmountCoin:   item.GetAmountCoin(),
		Direction:    item.GetDirection(),
		Reason:       item.GetReason(),
		BalanceAfter: item.GetBalanceAfter(),
		CreatedAtMS:  item.GetCreatedAtMs(),
	}
}

func selfGameStakePoolFromProto(item *gamev1.SelfGameStakePool) selfGameStakePoolDTO {
	if item == nil {
		return selfGameStakePoolDTO{}
	}
	return selfGameStakePoolDTO{
		AppCode:            item.GetAppCode(),
		GameID:             item.GetGameId(),
		StakeCoin:          item.GetStakeCoin(),
		BalanceCoin:        item.GetBalanceCoin(),
		ReservedCoin:       item.GetReservedCoin(),
		AvailableCoin:      item.GetAvailableCoin(),
		TargetBalanceCoin:  item.GetTargetBalanceCoin(),
		SafeBalanceCoin:    item.GetSafeBalanceCoin(),
		WarningBalanceCoin: item.GetWarningBalanceCoin(),
		DangerBalanceCoin:  item.GetDangerBalanceCoin(),
		Status:             item.GetStatus(),
		PoolLevel:          item.GetPoolLevel(),
		RequiredPoolCoin:   item.GetRequiredPoolCoin(),
		HumanWinCapacity:   item.GetHumanWinCapacity(),
		BotMatchEnabled:    item.GetBotMatchEnabled(),
		BlackReason:        item.GetBlackReason(),
		CreatedAtMS:        item.GetCreatedAtMs(),
		UpdatedAtMS:        item.GetUpdatedAtMs(),
	}
}

func selfGameNewUserPolicyFromProto(item *gamev1.SelfGameNewUserPolicy) selfGameNewUserPolicyDTO {
	if item == nil {
		return selfGameNewUserPolicyDTO{}
	}
	return selfGameNewUserPolicyDTO{
		AppCode:                         item.GetAppCode(),
		GameID:                          item.GetGameId(),
		Enabled:                         item.GetEnabled(),
		ProtectionRounds:                item.GetProtectionRounds(),
		ProtectionHours:                 item.GetProtectionHours(),
		MaxStakeCoin:                    item.GetMaxStakeCoin(),
		LifetimeSubsidyQuotaCoin:        item.GetLifetimeSubsidyQuotaCoin(),
		Day1SubsidyQuotaCoin:            item.GetDay1SubsidyQuotaCoin(),
		SingleRoundSubsidyCapCoin:       item.GetSingleRoundSubsidyCapCoin(),
		StrategyLevel:                   item.GetStrategyLevel(),
		LoseStreakProtectionEnabled:     item.GetLoseStreakProtectionEnabled(),
		LoseStreakTrigger:               item.GetLoseStreakTrigger(),
		NormalPhaseTargetWinRatePercent: item.GetNormalPhaseTargetWinRatePercent(),
		BlackPoolRobotForceWinEnabled:   item.GetBlackPoolRobotForceWinEnabled(),
		CreatedAtMS:                     item.GetCreatedAtMs(),
		UpdatedAtMS:                     item.GetUpdatedAtMs(),
	}
}

func diceRobotFromProto(item *gamev1.DiceRobot) diceRobotDTO {
	if item == nil {
		return diceRobotDTO{}
	}
	return diceRobotDTO{
		AppCode:          item.GetAppCode(),
		GameID:           item.GetGameId(),
		UserID:           strconv.FormatInt(item.GetUserId(), 10),
		UserIDNumber:     item.GetUserId(),
		Status:           item.GetStatus(),
		CreatedByAdminID: item.GetCreatedByAdminId(),
		CreatedAtMS:      item.GetCreatedAtMs(),
		UpdatedAtMS:      item.GetUpdatedAtMs(),
	}
}

func roomRPSConfigFromProto(item *gamev1.RoomRPSConfig) roomRPSConfigDTO {
	if item == nil {
		return roomRPSConfigDTO{}
	}
	gifts := make([]roomRPSStakeGiftDTO, 0, len(item.GetStakeGifts()))
	for _, gift := range item.GetStakeGifts() {
		// 礼物详情由 game-service 结合礼物配置补齐；admin-server 只保持展示字段和 ID 双写，不重新查礼物表。
		gifts = append(gifts, roomRPSStakeGiftDTO{
			GiftID:           roomRPSStakeGiftIDFromProto(gift),
			GiftIDNumber:     gift.GetGiftId(),
			GiftName:         gift.GetGiftName(),
			GiftIconURL:      gift.GetGiftIconUrl(),
			GiftAnimationURL: gift.GetGiftAnimationUrl(),
			GiftPriceCoin:    gift.GetGiftPriceCoin(),
			Enabled:          gift.GetEnabled(),
			SortOrder:        gift.GetSortOrder(),
		})
	}
	// DTO 只做 proto 到后台 JSON 的字段命名转换；配置默认值和合法性已经在 game-service/admin request 层处理。
	return roomRPSConfigDTO{
		AppCode:            item.GetAppCode(),
		GameID:             item.GetGameId(),
		Status:             item.GetStatus(),
		ChallengeTimeoutMS: item.GetChallengeTimeoutMs(),
		RevealCountdownMS:  item.GetRevealCountdownMs(),
		StakeGifts:         gifts,
		CreatedAtMS:        item.GetCreatedAtMs(),
		UpdatedAtMS:        item.GetUpdatedAtMs(),
	}
}

func roomRPSChallengeFromProto(item *gamev1.RoomRPSChallenge) roomRPSChallengeDTO {
	if item == nil {
		return roomRPSChallengeDTO{}
	}
	// 后台订单页要同时服务浏览器展示和问题排查：ID 用字符串保护前端精度，也保留 number 字段便于排序、复制和接口调试。
	// 胜负、结算状态、失败原因全部按 game-service 返回值展示，admin-server 不根据手势重新计算，避免和真实结算事实分叉。
	return roomRPSChallengeDTO{
		AppCode:            item.GetAppCode(),
		ChallengeID:        item.GetChallengeId(),
		RoomID:             item.GetRoomId(),
		RegionID:           item.GetRegionId(),
		Status:             item.GetStatus(),
		StakeGiftID:        roomRPSChallengeStakeGiftIDFromProto(item),
		StakeGiftIDNumber:  item.GetStakeGiftId(),
		StakeCoin:          item.GetStakeCoin(),
		Initiator:          roomRPSPlayerFromProto(item.GetInitiator()),
		Challenger:         roomRPSPlayerFromProto(item.GetChallenger()),
		WinnerUserID:       strconv.FormatInt(item.GetWinnerUserId(), 10),
		WinnerUserIDNumber: item.GetWinnerUserId(),
		SettlementStatus:   item.GetSettlementStatus(),
		FailureReason:      item.GetFailureReason(),
		TimeoutAtMS:        item.GetTimeoutAtMs(),
		RevealAtMS:         item.GetRevealAtMs(),
		CreatedAtMS:        item.GetCreatedAtMs(),
		MatchedAtMS:        item.GetMatchedAtMs(),
		SettledAtMS:        item.GetSettledAtMs(),
		UpdatedAtMS:        item.GetUpdatedAtMs(),
	}
}

func roomRPSStakeGiftIDFromProto(gift *gamev1.RoomRPSStakeGift) string {
	if gift == nil {
		return ""
	}
	if text := strings.TrimSpace(gift.GetGiftIdText()); text != "" {
		return text
	}
	if gift.GetGiftId() > 0 {
		return strconv.FormatInt(gift.GetGiftId(), 10)
	}
	return ""
}

func roomRPSChallengeStakeGiftIDFromProto(item *gamev1.RoomRPSChallenge) string {
	if item == nil {
		return ""
	}
	if text := strings.TrimSpace(item.GetStakeGiftIdText()); text != "" {
		return text
	}
	if item.GetStakeGiftId() > 0 {
		return strconv.FormatInt(item.GetStakeGiftId(), 10)
	}
	return ""
}

func roomRPSPlayerFromProto(item *gamev1.RoomRPSPlayer) roomRPSPlayerDTO {
	if item == nil {
		return roomRPSPlayerDTO{}
	}
	// 管理后台玩家 DTO 只展示订单内快照字段；头像昵称属于 App/IM 展示增强，后台如需用户资料应走独立用户查询。
	return roomRPSPlayerDTO{
		UserID:       strconv.FormatInt(item.GetUserId(), 10),
		UserIDNumber: item.GetUserId(),
		Gesture:      item.GetGesture(),
		Result:       item.GetResult(),
		BalanceAfter: item.GetBalanceAfter(),
		JoinedAtMS:   item.GetJoinedAtMs(),
	}
}
