package jitsi

import (
	"context"
	"fmt"
	"time"
)

// ========================================
// Breakpilot Drive Game Meeting Types
// ========================================

// GameMeetingMode represents different game video call modes
type GameMeetingMode string

const (
	GameMeetingCoop       GameMeetingMode = "coop"        // Co-Op voice/video
	GameMeetingChallenge  GameMeetingMode = "challenge"   // 1v1 face-off
	GameMeetingClassRace  GameMeetingMode = "class_race"  // Teacher supervises
	GameMeetingTeamHuddle GameMeetingMode = "team_huddle" // Quick team sync
)

// GameMeetingConfig holds configuration for game video meetings
type GameMeetingConfig struct {
	SessionID      string          `json:"session_id"`
	Mode           GameMeetingMode `json:"mode"`
	HostID         string          `json:"host_id"`
	HostName       string          `json:"host_name"`
	Players        []GamePlayer    `json:"players"`
	EnableVideo    bool            `json:"enable_video"`
	EnableVoice    bool            `json:"enable_voice"`
	TeacherID      string          `json:"teacher_id,omitempty"`
	TeacherName    string          `json:"teacher_name,omitempty"`
	ClassName      string          `json:"class_name,omitempty"`
}

// GamePlayer represents a player in the meeting
type GamePlayer struct {
	ID          string `json:"id"`
	Name        string `json:"name"`
	IsModerator bool   `json:"is_moderator,omitempty"`
}

// GameMeetingLink extends MeetingLink with game-specific info
type GameMeetingLink struct {
	*MeetingLink
	SessionID string          `json:"session_id"`
	Mode      GameMeetingMode `json:"mode"`
	Players   []string        `json:"players"`
}

// ========================================
// Game Meeting Creation
// ========================================

// CreateCoopMeeting creates a video call for Co-Op gameplay (2-4 players)
func (s *JitsiService) CreateCoopMeeting(ctx context.Context, config GameMeetingConfig) (*GameMeetingLink, error) {
	roomName := fmt.Sprintf("bp-coop-%s", config.SessionID[:8])

	meeting := Meeting{
		RoomName:    roomName,
		DisplayName: config.HostName,
		Subject:     "Breakpilot Drive - Co-Op Session",
		Moderator:   true,
		Config: &MeetingConfig{
			StartWithAudioMuted: !config.EnableVoice,
			StartWithVideoMuted: !config.EnableVideo,
			RequireDisplayName:  true,
			EnableLobby:         false, // Direct join for co-op
			DisableDeepLinking:  true,
		},
	}

	link, err := s.CreateMeetingLink(ctx, meeting)
	if err != nil {
		return nil, fmt.Errorf("failed to create co-op meeting: %w", err)
	}

	playerIDs := make([]string, len(config.Players))
	for i, p := range config.Players {
		playerIDs[i] = p.ID
	}

	return &GameMeetingLink{
		MeetingLink: link,
		SessionID:   config.SessionID,
		Mode:        GameMeetingCoop,
		Players:     playerIDs,
	}, nil
}

// CreateChallengeMeeting creates a 1v1 video call for challenges
func (s *JitsiService) CreateChallengeMeeting(ctx context.Context, config GameMeetingConfig, challengerName string, opponentName string) (*GameMeetingLink, error) {
	roomName := fmt.Sprintf("bp-challenge-%s", config.SessionID[:8])

	meeting := Meeting{
		RoomName:    roomName,
		DisplayName: challengerName,
		Subject:     fmt.Sprintf("Challenge: %s vs %s", challengerName, opponentName),
		Moderator:   false, // Both players are equal
		Config: &MeetingConfig{
			StartWithAudioMuted: false, // Voice enabled for trash talk
			StartWithVideoMuted: !config.EnableVideo,
			RequireDisplayName:  true,
			EnableLobby:         false,
			DisableDeepLinking:  true,
		},
	}

	link, err := s.CreateMeetingLink(ctx, meeting)
	if err != nil {
		return nil, fmt.Errorf("failed to create challenge meeting: %w", err)
	}

	return &GameMeetingLink{
		MeetingLink: link,
		SessionID:   config.SessionID,
		Mode:        GameMeetingChallenge,
		Players:     []string{config.HostID},
	}, nil
}

// CreateClassRaceMeeting creates a video call for teacher-supervised class races
func (s *JitsiService) CreateClassRaceMeeting(ctx context.Context, config GameMeetingConfig) (*GameMeetingLink, error) {
	roomName := fmt.Sprintf("bp-klasse-%s-%s",
		s.sanitizeRoomName(config.ClassName),
		time.Now().Format("150405"))

	// Teacher is moderator
	meeting := Meeting{
		RoomName:    roomName,
		DisplayName: config.TeacherName,
		Subject:     fmt.Sprintf("Klassenrennen: %s", config.ClassName),
		Moderator:   true,
		Config: &MeetingConfig{
			StartWithAudioMuted: true,  // Students muted by default
			StartWithVideoMuted: true,  // Video off for performance
			RequireDisplayName:  true,
			EnableLobby:         true,  // Teacher admits students
			EnableRecording:     false, // No recording for minors
			DisableDeepLinking:  true,
		},
		Features: &MeetingFeatures{
			Recording:     false,
			Transcription: false,
		},
	}

	link, err := s.CreateMeetingLink(ctx, meeting)
	if err != nil {
		return nil, fmt.Errorf("failed to create class race meeting: %w", err)
	}

	playerIDs := make([]string, len(config.Players))
	for i, p := range config.Players {
		playerIDs[i] = p.ID
	}

	return &GameMeetingLink{
		MeetingLink: link,
		SessionID:   config.SessionID,
		Mode:        GameMeetingClassRace,
		Players:     playerIDs,
	}, nil
}

// CreateTeamHuddleMeeting creates a quick sync meeting for teams
func (s *JitsiService) CreateTeamHuddleMeeting(ctx context.Context, config GameMeetingConfig, teamName string) (*GameMeetingLink, error) {
	roomName := fmt.Sprintf("bp-team-%s-%s",
		s.sanitizeRoomName(teamName),
		config.SessionID[:8])

	meeting := Meeting{
		RoomName:    roomName,
		DisplayName: config.HostName,
		Subject:     fmt.Sprintf("Team %s - Huddle", teamName),
		Duration:    5, // Short 5-minute huddles
		Moderator:   true,
		Config: &MeetingConfig{
			StartWithAudioMuted: false, // Voice on for quick sync
			StartWithVideoMuted: true,  // Video optional
			RequireDisplayName:  true,
			EnableLobby:         false,
			DisableDeepLinking:  true,
		},
	}

	link, err := s.CreateMeetingLink(ctx, meeting)
	if err != nil {
		return nil, fmt.Errorf("failed to create team huddle: %w", err)
	}

	playerIDs := make([]string, len(config.Players))
	for i, p := range config.Players {
		playerIDs[i] = p.ID
	}

	return &GameMeetingLink{
		MeetingLink: link,
		SessionID:   config.SessionID,
		Mode:        GameMeetingTeamHuddle,
		Players:     playerIDs,
	}, nil
}

// ========================================
// Game-Specific Meeting Configurations
// ========================================

// GetGameEmbedConfig returns optimized config for embedding in Unity WebGL
func (s *JitsiService) GetGameEmbedConfig(enableVideo bool, enableVoice bool) *MeetingConfig {
	return &MeetingConfig{
		StartWithAudioMuted: !enableVoice,
		StartWithVideoMuted: !enableVideo,
		RequireDisplayName:  true,
		EnableLobby:         false,
		DisableDeepLinking:  true, // Important for iframe embedding
	}
}

// BuildGameEmbedURL creates a URL optimized for Unity WebGL embedding
func (s *JitsiService) BuildGameEmbedURL(roomName string, playerName string, enableVideo bool, enableVoice bool) string {
	config := s.GetGameEmbedConfig(enableVideo, enableVoice)
	return s.BuildEmbedURL(roomName, playerName, config)
}

// BuildUnityIFrameParams returns parameters for Unity's WebGL iframe
func (s *JitsiService) BuildUnityIFrameParams(link *GameMeetingLink, playerName string) map[string]interface{} {
	return map[string]interface{}{
		"domain":      s.extractDomain(),
		"roomName":    link.RoomName,
		"displayName": playerName,
		"jwt":         link.JWT,
		"configOverwrite": map[string]interface{}{
			"startWithAudioMuted":  false,
			"startWithVideoMuted":  true,
			"disableDeepLinking":   true,
			"prejoinPageEnabled":   false,
			"enableWelcomePage":    false,
			"enableClosePage":      false,
			"disableInviteFunctions": true,
		},
		"interfaceConfigOverwrite": map[string]interface{}{
			"DISABLE_JOIN_LEAVE_NOTIFICATIONS": true,
			"MOBILE_APP_PROMO":                 false,
			"SHOW_CHROME_EXTENSION_BANNER":     false,
			"TOOLBAR_BUTTONS": []string{
				"microphone", "camera", "hangup", "chat",
			},
		},
	}
}

// ========================================
// Spectator Mode (for teachers/parents)
// ========================================

// CreateSpectatorLink creates a view-only link for observers
func (s *JitsiService) CreateSpectatorLink(ctx context.Context, roomName string, spectatorName string) (*MeetingLink, error) {
	meeting := Meeting{
		RoomName:    roomName,
		DisplayName: fmt.Sprintf("[Zuschauer] %s", spectatorName),
		Moderator:   false,
		Config: &MeetingConfig{
			StartWithAudioMuted: true,
			StartWithVideoMuted: true,
			DisableDeepLinking:  true,
		},
	}

	return s.CreateMeetingLink(ctx, meeting)
}

// ========================================
// Helper Functions
// ========================================

// extractDomain extracts the domain from baseURL
func (s *JitsiService) extractDomain() string {
	// Remove protocol prefix
	domain := s.baseURL
	if len(domain) > 8 && domain[:8] == "https://" {
		domain = domain[8:]
	} else if len(domain) > 7 && domain[:7] == "http://" {
		domain = domain[7:]
	}
	// Remove port if present
	for i, c := range domain {
		if c == ':' || c == '/' {
			domain = domain[:i]
			break
		}
	}
	return domain
}

// ValidateGameMeetingConfig validates configuration before creating meeting
func ValidateGameMeetingConfig(config GameMeetingConfig) error {
	if config.SessionID == "" {
		return fmt.Errorf("session_id is required")
	}

	if config.Mode == "" {
		return fmt.Errorf("mode is required")
	}

	if config.HostID == "" {
		return fmt.Errorf("host_id is required")
	}

	if config.HostName == "" {
		return fmt.Errorf("host_name is required")
	}

	switch config.Mode {
	case GameMeetingCoop:
		if len(config.Players) < 2 || len(config.Players) > 4 {
			return fmt.Errorf("co-op mode requires 2-4 players")
		}
	case GameMeetingChallenge:
		if len(config.Players) != 2 {
			return fmt.Errorf("challenge mode requires exactly 2 players")
		}
	case GameMeetingClassRace:
		if config.TeacherID == "" || config.TeacherName == "" {
			return fmt.Errorf("class race mode requires teacher info")
		}
		if config.ClassName == "" {
			return fmt.Errorf("class race mode requires class name")
		}
	case GameMeetingTeamHuddle:
		if len(config.Players) < 2 {
			return fmt.Errorf("team huddle requires at least 2 players")
		}
	default:
		return fmt.Errorf("unknown game meeting mode: %s", config.Mode)
	}

	return nil
}
