package main

import (
	"context"
	"encoding/json"
	"fmt"
	"net/http"
	"time"
)

// setupWebServer initializes the HTTP server for admin interface
func (w *World) setupWebServer() error {
	if w.config.WebPort == 0 {
		return nil // Web server disabled
	}

	mux := http.NewServeMux()

	// API endpoints
	mux.HandleFunc("/api/status", w.handleStatus)
	mux.HandleFunc("/api/clients", w.handleClients)
	mux.HandleFunc("/api/zones", w.handleZones)
	mux.HandleFunc("/api/stats", w.handleStats)
	mux.HandleFunc("/api/time", w.handleWorldTime)
	mux.HandleFunc("/api/shutdown", w.handleShutdown)

	// Administrative endpoints
	mux.HandleFunc("/api/admin/reload", w.handleReload)
	mux.HandleFunc("/api/admin/broadcast", w.handleBroadcast)
	mux.HandleFunc("/api/admin/kick", w.handleKickClient)

	// Peer management endpoints
	mux.HandleFunc("/api/peers", w.handlePeers)
	mux.HandleFunc("/api/peers/sync", w.handlePeerSync)

	// Console command interface
	mux.HandleFunc("/api/console", w.handleConsoleCommand)

	// Static health check
	mux.HandleFunc("/health", w.handleHealth)

	// @TODO: Add authentication middleware
	// @TODO: Add rate limiting middleware
	// @TODO: Add CORS middleware for browser access
	// @TODO: Add TLS support with cert/key files

	addr := fmt.Sprintf("%s:%d", w.config.WebAddr, w.config.WebPort)
	w.webServer = &http.Server{
		Addr:         addr,
		Handler:      mux,
		ReadTimeout:  10 * time.Second,
		WriteTimeout: 10 * time.Second,
	}

	return nil
}

// Core API handlers

// handleHealth provides a simple health check endpoint
func (w *World) handleHealth(rw http.ResponseWriter, r *http.Request) {
	rw.Header().Set("Content-Type", "application/json")
	json.NewEncoder(rw).Encode(map[string]string{"status": "ok"})
}

// handleStatus returns comprehensive server status information
func (w *World) handleStatus(rw http.ResponseWriter, r *http.Request) {
	rw.Header().Set("Content-Type", "application/json")

	status := map[string]any{
		"status":      "running",
		"uptime":      time.Since(w.stats.StartTime).Seconds(),
		"version":     Version,
		"locked":      w.config.WorldLocked,
		"primary":     w.config.IsPrimary,
		"threaded":    w.config.ThreadedLoad,
		"data_loaded": w.isDataLoaded(),
		"world_time":  w.getWorldTime(),
	}

	json.NewEncoder(rw).Encode(status)
}

// handleClients returns list of connected clients
func (w *World) handleClients(rw http.ResponseWriter, r *http.Request) {
	rw.Header().Set("Content-Type", "application/json")

	w.clientsMux.RLock()
	clients := make([]*ClientInfo, 0, len(w.clients))
	for _, client := range w.clients {
		clients = append(clients, client)
	}
	w.clientsMux.RUnlock()

	json.NewEncoder(rw).Encode(map[string]any{
		"count":   len(clients),
		"clients": clients,
	})
}

// handleZones returns list of zone servers
func (w *World) handleZones(rw http.ResponseWriter, r *http.Request) {
	rw.Header().Set("Content-Type", "application/json")

	w.zonesMux.RLock()
	zones := make([]*ZoneInfo, 0, len(w.zones))
	for _, zone := range w.zones {
		zones = append(zones, zone)
	}
	w.zonesMux.RUnlock()

	json.NewEncoder(rw).Encode(map[string]any{
		"count": len(zones),
		"zones": zones,
	})
}

// handleStats returns detailed server statistics
func (w *World) handleStats(rw http.ResponseWriter, r *http.Request) {
	rw.Header().Set("Content-Type", "application/json")

	w.statsMux.RLock()
	stats := w.stats
	w.statsMux.RUnlock()

	// Add UDP server stats if available
	if w.udpServer != nil {
		serverStats := w.udpServer.GetStats()
		stats.TotalConnections = int64(serverStats.ConnectionCount)
	}

	json.NewEncoder(rw).Encode(stats)
}

// handleWorldTime returns current game world time
func (w *World) handleWorldTime(rw http.ResponseWriter, r *http.Request) {
	rw.Header().Set("Content-Type", "application/json")
	json.NewEncoder(rw).Encode(w.getWorldTime())
}

// Administrative handlers

// handleShutdown initiates graceful server shutdown
func (w *World) handleShutdown(rw http.ResponseWriter, r *http.Request) {
	if r.Method != http.MethodPost {
		http.Error(rw, "Method not allowed", http.StatusMethodNotAllowed)
		return
	}

	// @TODO: Add authentication check
	// @TODO: Add confirmation parameter
	// @TODO: Add delay parameter

	rw.Header().Set("Content-Type", "application/json")
	json.NewEncoder(rw).Encode(map[string]string{"status": "shutdown initiated"})

	go func() {
		time.Sleep(time.Second) // Allow response to be sent
		w.Shutdown()
	}()
}

// handleReload reloads game data
func (w *World) handleReload(rw http.ResponseWriter, r *http.Request) {
	if r.Method != http.MethodPost {
		http.Error(rw, "Method not allowed", http.StatusMethodNotAllowed)
		return
	}

	// @TODO: Add authentication check
	// @TODO: Implement selective reloading (items, spells, quests, etc.)
	// @TODO: Add progress reporting

	rw.Header().Set("Content-Type", "application/json")
	json.NewEncoder(rw).Encode(map[string]string{"status": "reload not implemented"})
}

// handleBroadcast sends server-wide message
func (w *World) handleBroadcast(rw http.ResponseWriter, r *http.Request) {
	if r.Method != http.MethodPost {
		http.Error(rw, "Method not allowed", http.StatusMethodNotAllowed)
		return
	}

	// @TODO: Add authentication check
	// @TODO: Parse message from request body
	// @TODO: Validate message content
	// @TODO: Send to all connected clients

	rw.Header().Set("Content-Type", "application/json")
	json.NewEncoder(rw).Encode(map[string]string{"status": "broadcast not implemented"})
}

// handleKickClient disconnects a specific client
func (w *World) handleKickClient(rw http.ResponseWriter, r *http.Request) {
	if r.Method != http.MethodPost {
		http.Error(rw, "Method not allowed", http.StatusMethodNotAllowed)
		return
	}

	// @TODO: Add authentication check
	// @TODO: Parse client ID from request
	// @TODO: Find and disconnect client
	// @TODO: Log kick action

	rw.Header().Set("Content-Type", "application/json")
	json.NewEncoder(rw).Encode(map[string]string{"status": "kick not implemented"})
}

// Peer management handlers

// handlePeers returns list of peer servers
func (w *World) handlePeers(rw http.ResponseWriter, r *http.Request) {
	rw.Header().Set("Content-Type", "application/json")

	peers := make([]map[string]any, 0)
	for _, peer := range w.config.PeerServers {
		peerInfo := map[string]any{
			"address": peer.Address,
			"port":    peer.Port,
			"status":  "unknown", // @TODO: Implement peer status checking
		}
		peers = append(peers, peerInfo)
	}

	json.NewEncoder(rw).Encode(map[string]any{
		"count": len(peers),
		"peers": peers,
	})
}

// handlePeerSync synchronizes data with peer servers
func (w *World) handlePeerSync(rw http.ResponseWriter, r *http.Request) {
	if r.Method != http.MethodPost {
		http.Error(rw, "Method not allowed", http.StatusMethodNotAllowed)
		return
	}

	// @TODO: Add authentication check
	// @TODO: Implement peer synchronization
	// @TODO: Return sync status and results

	rw.Header().Set("Content-Type", "application/json")
	json.NewEncoder(rw).Encode(map[string]string{"status": "peer sync not implemented"})
}

// Console command handler

// handleConsoleCommand executes administrative commands
func (w *World) handleConsoleCommand(rw http.ResponseWriter, r *http.Request) {
	if r.Method != http.MethodPost {
		http.Error(rw, "Method not allowed", http.StatusMethodNotAllowed)
		return
	}

	// @TODO: Add authentication check
	// @TODO: Parse command from request body
	// @TODO: Validate command permissions
	// @TODO: Execute command and return results
	// @TODO: Log command execution

	rw.Header().Set("Content-Type", "application/json")
	json.NewEncoder(rw).Encode(map[string]string{"status": "console commands not implemented"})
}

// Helper methods for web handlers

// getWorldTime returns thread-safe copy of world time
func (w *World) getWorldTime() WorldTime {
	w.worldTimeMux.RLock()
	defer w.worldTimeMux.RUnlock()
	return w.worldTime
}

// startWebServer starts the web server in a goroutine
func (w *World) startWebServer() {
	if w.webServer == nil {
		return
	}

	go func() {
		if err := w.webServer.ListenAndServe(); err != nil && err != http.ErrServerClosed {
			fmt.Printf("Web server error: %v\n", err)
		}
	}()
}

// stopWebServer gracefully stops the web server
func (w *World) stopWebServer() error {
	if w.webServer == nil {
		return nil
	}

	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()

	return w.webServer.Shutdown(ctx)
}
