//go:build js && wasm
// +build js,wasm

package main

import (
	"encoding/base64"
	"log"
	"syscall/js"
	"time"
)

// notifyWasmReady signalisiert JavaScript dass WASM vollständig geladen ist
func (g *Game) notifyWasmReady() {
	if readyFunc := js.Global().Get("onWasmReady"); !readyFunc.IsUndefined() {
		readyFunc.Invoke()
		log.Println("✅ WASM Ready-Signal an JavaScript gesendet")
	}
}

// setupJavaScriptBridge registriert JavaScript-Funktionen für HTML-Menü Interaktion
func (g *Game) setupJavaScriptBridge() {
	// startGame(mode, playerName, roomID, teamName, isHost)
	startGameFunc := js.FuncOf(func(this js.Value, args []js.Value) interface{} {
		if len(args) < 2 {
			log.Println("❌ startGame: Nicht genug Argumente")
			return nil
		}

		mode := args[0].String()       // "solo" oder "coop"
		playerName := args[1].String() // Spielername

		// Spieler-Daten setzen
		g.playerName = playerName
		g.gameMode = mode
		g.savePlayerName(playerName)

		if mode == "solo" {
			// Solo Mode - Jetzt standardmäßig OFFLINE
			g.isHost = true
			g.startOfflineGame()
			log.Printf("🎮 Solo-Spiel OFFLINE gestartet: %s", playerName)
			return nil
		} else if mode == "coop" && len(args) >= 5 {
			// Co-op Mode - in die Lobby
			roomID := args[2].String()
			teamName := args[3].String()
			isHost := args[4].Bool()

			g.roomID = roomID
			g.teamName = teamName
			g.isHost = isHost
			g.appState = StateLobby

			log.Printf("🎮 Co-op-Lobby erstellt: %s (Room: %s, Team: %s, Host: %v)", playerName, roomID, teamName, isHost)
		}

		// Verbindung starten
		go g.connectAndStart()

		return nil
	})

	// requestLeaderboard()
	requestLeaderboardFunc := js.FuncOf(func(this js.Value, args []js.Value) interface{} {
		log.Println("📊 Leaderboard angefordert")
		go g.requestLeaderboard()
		return nil
	})

	// setMusicVolume(volume)
	setMusicVolumeFunc := js.FuncOf(func(this js.Value, args []js.Value) interface{} {
		if len(args) > 0 {
			volume := args[0].Float()
			g.audio.SetMusicVolume(volume)
			log.Printf("🎵 Musik-Lautstärke: %.0f%%", volume*100)
		}
		return nil
	})

	// setSFXVolume(volume)
	setSFXVolumeFunc := js.FuncOf(func(this js.Value, args []js.Value) interface{} {
		if len(args) > 0 {
			volume := args[0].Float()
			g.audio.SetSFXVolume(volume)
			log.Printf("🔊 SFX-Lautstärke: %.0f%%", volume*100)
		}
		return nil
	})

	// startGameFromLobby_WASM() - Host startet Spiel aus HTML Lobby
	startGameFromLobbyFunc := js.FuncOf(func(this js.Value, args []js.Value) interface{} {
		log.Println("🎮 Host startet Spiel aus HTML Lobby")
		go g.sendStartRequest()
		return nil
	})

	// setTeamName_WASM(teamName) - Host setzt Team-Namen
	setTeamNameFunc := js.FuncOf(func(this js.Value, args []js.Value) interface{} {
		if len(args) > 0 {
			teamName := args[0].String()
			g.teamName = teamName
			log.Printf("🏷️  Team-Name gesetzt: '%s'", teamName)
			go g.sendSetTeamNameInput(teamName)
		}
		return nil
	})

	// togglePresentationMode_WASM()
	togglePresFunc := js.FuncOf(func(this js.Value, args []js.Value) interface{} {
		log.Println("⌨️ F1: Toggle Presentation Mode")
		// Simulate F1 key press in WASM
		if g.appState == StatePresentation {
			g.appState = StateMenu
			g.disconnectFromServer()
			// JS Callback to hide screen
			js.Global().Call("showMainMenu")
		} else {
			g.appState = StatePresentation
			g.presAssets = nil
			g.presQuoteTime = time.Now()
			g.gameMode = "coop"
			g.isHost = true
			g.roomID = "PRES" + generateRoomCode()
			g.playerName = "PRESENTATION"
			go g.connectAndStart()

			joinURL := "https://escape-from-school.de/?room=" + g.roomID
			g.presQRCode = generateQRCode(joinURL)
			g.notifyPresentationStarted_Platform(g.roomID)
		}
		return nil
	})

	// Im globalen Scope registrieren
	js.Global().Set("startGame", startGameFunc)
	js.Global().Set("requestLeaderboard", requestLeaderboardFunc)
	js.Global().Set("setMusicVolume", setMusicVolumeFunc)
	js.Global().Set("setSFXVolume", setSFXVolumeFunc)
	js.Global().Set("startGameFromLobby_WASM", startGameFromLobbyFunc)
	js.Global().Set("setTeamName_WASM", setTeamNameFunc)
	js.Global().Set("togglePresentationMode_WASM", togglePresFunc)

	log.Println("✅ JavaScript Bridge registriert")
	log.Printf("🔍 window.startGame defined: %v", !js.Global().Get("startGame").IsUndefined())
	log.Printf("🔍 window.startGameFromLobby_WASM defined: %v", !js.Global().Get("startGameFromLobby_WASM").IsUndefined())
}

// Leaderboard an JavaScript senden
func (g *Game) sendLeaderboardToJS() {
	g.leaderboardMutex.Lock()
	entries := make([]interface{}, len(g.leaderboard))
	for i, entry := range g.leaderboard {
		entries[i] = map[string]interface{}{
			"player_name": entry.PlayerName,
			"score":       entry.Score,
			"player_code": entry.PlayerCode,
		}
	}
	g.leaderboardMutex.Unlock()

	// JavaScript-Funktion aufrufen
	if updateFunc := js.Global().Get("updateLeaderboard"); !updateFunc.IsUndefined() {
		jsEntries := js.ValueOf(entries)
		updateFunc.Invoke(jsEntries)
		log.Printf("📤 Leaderboard an JavaScript gesendet: %d Einträge", len(entries))
	}
}

// Game Over Screen an JavaScript senden
func (g *Game) sendGameOverToJS(score int) {
	if gameOverFunc := js.Global().Get("showGameOver"); !gameOverFunc.IsUndefined() {
		gameOverFunc.Invoke(score)
		log.Printf("💀 Game Over an JavaScript gesendet: Score=%d", score)
	}
}

// Lobby Player List an JavaScript senden
func (g *Game) sendLobbyPlayersToJS() {
	g.stateMutex.Lock()
	players := make([]interface{}, 0, len(g.gameState.Players))
	hostID := g.gameState.HostID
	teamName := g.gameState.TeamName

	for id, p := range g.gameState.Players {
		name := p.Name
		if name == "" {
			name = id
		}
		isHost := (id == hostID)
		players = append(players, map[string]interface{}{
			"name":    name,
			"is_host": isHost,
		})
	}
	g.stateMutex.Unlock()

	// JavaScript-Funktion aufrufen
	if updateFunc := js.Global().Get("updateLobbyPlayers"); !updateFunc.IsUndefined() {
		jsPlayers := js.ValueOf(players)
		updateFunc.Invoke(jsPlayers)
		log.Printf("👥 Lobby-Spieler an JavaScript gesendet: %d Spieler", len(players))
	}

	// Team-Name an JavaScript senden
	if updateTeamFunc := js.Global().Get("updateLobbyTeamName"); !updateTeamFunc.IsUndefined() {
		myID := g.getMyPlayerID()
		isHost := (myID == hostID)
		updateTeamFunc.Invoke(teamName, isHost)
		log.Printf("🏷️  Team-Name an JavaScript gesendet: '%s' (isHost: %v)", teamName, isHost)
	}
}

// notifyPresentationStarted benachrichtigt JS dass der Presi-Modus aktiv ist
func (g *Game) notifyPresentationStarted(roomID string, qrCode []byte) {
	if presFunc := js.Global().Get("onPresentationStarted"); !presFunc.IsUndefined() {
		// Konvertiere QR Code zu Base64 für JS
		qrBase64 := ""
		if qrCode != nil {
			qrBase64 = "data:image/png;base64," + base64.StdEncoding.EncodeToString(qrCode)
		}
		presFunc.Invoke(roomID, qrBase64)
		log.Printf("📺 Präsentationsmodus an JS signalisiert: %s", roomID)
	}
}

// updatePresentationState sendet den aktuellen Status (Spieler, Emotes) an JS
func (g *Game) updatePresentationState() {
	if updateFunc := js.Global().Get("onPresentationUpdate"); !updateFunc.IsUndefined() {
		g.stateMutex.Lock()
		players := g.gameState.Players
		g.stateMutex.Unlock()

		// Vereinfachte Spieler-Daten für JS
		jsPlayers := make([]interface{}, 0)
		for _, p := range players {
			if !p.IsAlive || p.Name == "PRESENTATION" {
				continue
			}
			jsPlayers = append(jsPlayers, map[string]interface{}{
				"id":    p.ID,
				"x":     p.X,
				"y":     p.Y,
				"vy":    p.VY,
				"state": p.State,
			})
		}
		updateFunc.Invoke(jsPlayers)
	}
}
