package roomapi

import (
	"context"
	"io"
	"net/http"
	"time"

	"hyapp/pkg/tencentrtc"
	"hyapp/services/gateway-service/internal/client"
	"hyapp/services/gateway-service/internal/transport/http/appapi"
	"hyapp/services/gateway-service/internal/transport/http/giftlimit"
	"hyapp/services/gateway-service/internal/transport/http/httproutes"
)

// ObjectUploader 是房间专用媒体上传所需的最小 COS 能力。
type ObjectUploader interface {
	PutObject(ctx context.Context, key string, reader io.Reader, sizeBytes int64, contentType string) (string, error)
}

type objectURLVerifier interface {
	OwnsObjectURL(objectURL string, objectKey string) bool
}

type roomDiscoveryCapabilityReader interface {
	RoomDiscoveryAllRegions(ctx context.Context, appCode string) (bool, error)
}

// Handler owns room-facing HTTP endpoints in gateway.
// It keeps gateway as protocol adapter only: room state still belongs to room-service.
type Handler struct {
	roomClient          client.RoomClient
	roomGuardClient     client.RoomGuardClient
	roomQueryClient     client.RoomQueryClient
	roomVIPClient       client.RoomVIPFeatureClient
	roomMediaGuard      client.RoomMediaGuardClient
	objectUploader      ObjectUploader
	objectURLVerifier   objectURLVerifier
	userProfileClient   client.UserProfileClient
	userCountryClient   client.UserCountryQueryClient
	userRegionClient    client.UserRegionClient
	userSocialClient    client.UserSocialClient
	userHostClient      client.UserHostClient
	appConfigReader     appapi.ConfigReader
	giftComboReader     giftComboConfigReader
	giftQuantityReader  giftQuantityPresetReader
	walletClient        client.WalletClient
	giftPanelCache      *roomGiftPanelConfigCache
	growthLevelClient   client.GrowthLevelClient
	achievementClient   client.AchievementClient
	giftCapacityEnabled bool
	giftCapacityLimiter giftlimit.Limiter
	giftRequestTimeout  time.Duration
	giftMaxTargets      int
	giftMaxCount        int
	giftMaxUnits        int
	rtcTokenConfig      tencentrtc.TokenConfig

	// gift-panel 的预算保留在 handler 内，生产使用固定安全值；测试可缩短预算验证真实超时分支，
	// 避免把 Flutter 的 15 秒客户端超时当成后端取消机制。
	giftPanelTotalBudget         time.Duration
	giftPanelRecipientCoreBudget time.Duration
}

type Config struct {
	RoomClient          client.RoomClient
	RoomGuardClient     client.RoomGuardClient
	RoomQueryClient     client.RoomQueryClient
	UserProfileClient   client.UserProfileClient
	UserCountryClient   client.UserCountryQueryClient
	UserRegionClient    client.UserRegionClient
	UserSocialClient    client.UserSocialClient
	UserHostClient      client.UserHostClient
	AppConfigReader     appapi.ConfigReader
	WalletClient        client.WalletClient
	GrowthLevelClient   client.GrowthLevelClient
	AchievementClient   client.AchievementClient
	GiftCapacityEnabled bool
	GiftCapacityLimiter giftlimit.Limiter
	GiftRequestTimeout  time.Duration
	GiftMaxTargets      int
	GiftMaxCount        int
	GiftMaxUnits        int
	RTCTokenConfig      tencentrtc.TokenConfig
	ObjectUploader      ObjectUploader
}

func New(config Config) *Handler {
	giftRequestTimeout := config.GiftRequestTimeout
	if giftRequestTimeout <= 0 {
		giftRequestTimeout = 5 * time.Second
	}
	giftMaxTargets := config.GiftMaxTargets
	if giftMaxTargets <= 0 {
		giftMaxTargets = 30
	}
	giftMaxCount := config.GiftMaxCount
	if giftMaxCount <= 0 {
		giftMaxCount = 999
	}
	giftMaxUnits := config.GiftMaxUnits
	if giftMaxUnits <= 0 {
		giftMaxUnits = 5_000
	}
	comboReader, _ := any(config.AppConfigReader).(giftComboConfigReader)
	giftQuantityReader, _ := any(config.AppConfigReader).(giftQuantityPresetReader)
	roomVIPClient, _ := any(config.RoomClient).(client.RoomVIPFeatureClient)
	roomMediaGuard, _ := any(config.RoomGuardClient).(client.RoomMediaGuardClient)
	urlVerifier, _ := any(config.ObjectUploader).(objectURLVerifier)
	return &Handler{
		roomClient:                   config.RoomClient,
		roomGuardClient:              config.RoomGuardClient,
		roomQueryClient:              config.RoomQueryClient,
		roomVIPClient:                roomVIPClient,
		roomMediaGuard:               roomMediaGuard,
		objectUploader:               config.ObjectUploader,
		objectURLVerifier:            urlVerifier,
		userProfileClient:            config.UserProfileClient,
		userCountryClient:            config.UserCountryClient,
		userRegionClient:             config.UserRegionClient,
		userSocialClient:             config.UserSocialClient,
		userHostClient:               config.UserHostClient,
		appConfigReader:              config.AppConfigReader,
		giftComboReader:              comboReader,
		giftQuantityReader:           giftQuantityReader,
		walletClient:                 config.WalletClient,
		giftPanelCache:               newRoomGiftPanelConfigCache(45 * time.Second),
		growthLevelClient:            config.GrowthLevelClient,
		achievementClient:            config.AchievementClient,
		giftCapacityEnabled:          config.GiftCapacityEnabled,
		giftCapacityLimiter:          config.GiftCapacityLimiter,
		giftRequestTimeout:           giftRequestTimeout,
		giftMaxTargets:               giftMaxTargets,
		giftMaxCount:                 giftMaxCount,
		giftMaxUnits:                 giftMaxUnits,
		rtcTokenConfig:               config.RTCTokenConfig,
		giftPanelTotalBudget:         roomGiftPanelTotalBudget,
		giftPanelRecipientCoreBudget: roomGiftPanelRecipientCoreBudget,
	}
}

func (h *Handler) RoomHandlers() httproutes.RoomHandlers {
	return httproutes.RoomHandlers{
		GetMyRoom:               h.getMyRoom,
		ListRoomFeeds:           h.listRoomFeeds,
		ListRoomFilters:         h.listRoomFilters,
		ListRooms:               h.listRooms,
		GetCurrentRoom:          h.getCurrentRoom,
		GetRoomSnapshot:         h.getRoomSnapshot,
		GetRoomDetail:           h.getRoomDetail,
		GetRoomShare:            h.getRoomShare,
		GetRoomShareLanding:     h.getRoomShareLanding,
		ListRoomOnlineUsers:     h.listRoomOnlineUsers,
		ListRoomBannedUsers:     h.listRoomBannedUsers,
		GetRoomContributionRank: h.getRoomContributionRank,
		GetRoomGiftPanel:        h.getRoomGiftPanel,
		GetRoomRocket:           h.getRoomRocket,
		FollowRoom:              h.handleRoomFollow,
		CreateRoom:              h.createRoom,
		UpdateRoomProfile:       h.updateRoomProfile,
		SaveRoomBackground:      h.saveRoomBackground,
		ListRoomBackgrounds:     h.listRoomBackgrounds,
		SetRoomBackground:       h.setRoomBackground,
		UploadRoomCover:         h.uploadRoomCover,
		UploadRoomBackground:    h.uploadRoomBackground,
		UploadRoomImage:         h.uploadRoomImage,
		SaveRoomBorder:          h.saveRoomBorder,
		ApplyRoomDecoration:     h.applyRoomDecoration,
		SendRoomImage:           h.sendRoomImage,
		JoinRoom:                h.joinRoom,
		RoomHeartbeat:           h.roomHeartbeat,
		LeaveRoom:               h.leaveRoom,
		CloseRoom:               h.closeRoom,
		MicUp:                   h.micUp,
		MicDown:                 h.micDown,
		ChangeMicSeat:           h.changeMicSeat,
		ConfirmMicPublishing:    h.confirmMicPublishing,
		MicHeartbeat:            h.micHeartbeat,
		SetMicMute:              h.setMicMute,
		SetMicSeatLock:          h.setMicSeatLock,
		SetChatEnabled:          h.setChatEnabled,
		SetRoomPassword:         h.setRoomPassword,
		SetRoomAdmin:            h.setRoomAdmin,
		MuteUser:                h.muteUser,
		KickUser:                h.kickUser,
		UnbanUser:               h.unbanUser,
		SendGift:                h.sendGift,
		SendGiftBatch:           h.sendGiftBatch,
		SendGiftV2:              h.sendGiftV2,
	}
}

func (h *Handler) IssueTencentRTCToken(writer http.ResponseWriter, request *http.Request) {
	h.issueTencentRTCToken(writer, request)
}

func (h *Handler) BatchRoomDisplayProfiles(writer http.ResponseWriter, request *http.Request) {
	h.batchRoomDisplayProfiles(writer, request)
}

func (h *Handler) BatchUserVoiceRoomPresences(writer http.ResponseWriter, request *http.Request) {
	h.batchUserVoiceRoomPresences(writer, request)
}
