// Package tencentrtc contains the gateway-owned Tencent RTC token boundary.
package tencentrtc

import (
	"fmt"
	"strconv"
	"time"

	"hyapp/pkg/roomid"
	"hyapp/pkg/tencentsig"
)

const (
	// RoomIDTypeString means clients must use TRTC strRoomId, not numeric roomId.
	RoomIDTypeString = "string"
	// AppSceneVoiceChatRoom is the first supported RTC scene for room audio.
	AppSceneVoiceChatRoom = "voice_chat_room"
	// RoleAudience is the safe default; publishing audio requires a later MicUp flow.
	RoleAudience = "audience"
)

// TokenConfig describes the explicit RTC application used by gateway token signing.
type TokenConfig struct {
	// Enabled must be true before gateway issues RTC UserSig credentials.
	Enabled bool
	// SDKAppID is the Tencent RTC application ID.
	SDKAppID int64
	// SecretKey signs UserSig and must stay server-side.
	SecretKey string
	// TTL controls the RTC UserSig validity window.
	TTL time.Duration
	// RoomIDType is fixed to "string" in v1 to avoid TRTC roomId/strRoomId drift.
	RoomIDType string
	// AppScene is fixed to voice_chat_room until product introduces more RTC scenes.
	AppScene string
}

// TokenResult is returned by gateway-service after room-service presence is verified.
type TokenResult struct {
	SDKAppID      int64  `json:"sdk_app_id"`
	UserID        string `json:"user_id"`
	RTCUserID     string `json:"rtc_user_id"`
	UserSig       string `json:"user_sig"`
	ExpireAtMS    int64  `json:"expire_at_ms"`
	RoomID        string `json:"room_id"`
	RTCRoomID     string `json:"rtc_room_id"`
	RTCRoomIDType string `json:"rtc_room_id_type"`
	StrRoomID     string `json:"str_room_id"`
	AppScene      string `json:"app_scene"`
	Role          string `json:"role"`
}

// FormatUserID converts the internal immutable user_id to Tencent RTC UserID.
func FormatUserID(userID int64) string {
	// Decimal user_id matches Tencent IM identifier and keeps troubleshooting one-to-one.
	return strconv.FormatInt(userID, 10)
}

// GenerateToken signs a Tencent RTC UserSig and attaches the explicit string room mapping.
func GenerateToken(cfg TokenConfig, userID int64, targetRoomID string, now time.Time) (TokenResult, error) {
	if err := ValidateConfig(cfg); err != nil {
		return TokenResult{}, err
	}
	if userID <= 0 {
		// RTC UserID must always come from an authenticated internal user_id.
		return TokenResult{}, fmt.Errorf("tencent rtc user_id is invalid")
	}
	if !roomid.ValidStringID(targetRoomID) {
		// This guard protects package callers; gateway maps this case to INVALID_ARGUMENT first.
		return TokenResult{}, fmt.Errorf("room_id is invalid for tencent rtc")
	}

	rtcUserID := FormatUserID(userID)
	userSig, err := tencentsig.GenerateUserSig(tencentsig.Config{
		SDKAppID:  cfg.SDKAppID,
		SecretKey: cfg.SecretKey,
		TTL:       cfg.TTL,
	}, rtcUserID, now)
	if err != nil {
		return TokenResult{}, err
	}

	return TokenResult{
		SDKAppID:      userSig.SDKAppID,
		UserID:        rtcUserID,
		RTCUserID:     rtcUserID,
		UserSig:       userSig.UserSig,
		ExpireAtMS:    userSig.ExpireAtMS,
		RoomID:        targetRoomID,
		RTCRoomID:     targetRoomID,
		RTCRoomIDType: RoomIDTypeString,
		StrRoomID:     targetRoomID,
		AppScene:      AppSceneVoiceChatRoom,
		Role:          RoleAudience,
	}, nil
}

// ValidateConfig verifies gateway can safely sign RTC tokens before calling room-service.
func ValidateConfig(cfg TokenConfig) error {
	if !cfg.Enabled || cfg.SDKAppID <= 0 || cfg.SecretKey == "" || cfg.TTL <= 0 {
		// Gateway must fail closed when RTC credentials are incomplete or disabled.
		return fmt.Errorf("tencent rtc token config is incomplete")
	}
	if cfg.RoomIDType != RoomIDTypeString || cfg.AppScene != AppSceneVoiceChatRoom {
		// The first RTC version only supports TRTC strRoomId for voice chat rooms.
		return fmt.Errorf("tencent rtc policy is unsupported")
	}

	return nil
}
