package main

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

// WebServer provides HTTP endpoints for monitoring
type WebServer struct {
	config      WebServerConfig
	loginServer *LoginServer
	server      *http.Server
}

// NewWebServer creates a new web monitoring server
func NewWebServer(config WebServerConfig, loginServer *LoginServer) (*WebServer, error) {
	ws := &WebServer{
		config:      config,
		loginServer: loginServer,
	}

	mux := http.NewServeMux()
	mux.HandleFunc("/status", ws.handleStatus)
	mux.HandleFunc("/worlds", ws.handleWorlds)
	mux.HandleFunc("/stats", ws.handleStats)
	mux.HandleFunc("/health", ws.handleHealth)

	ws.server = &http.Server{
		Addr:         fmt.Sprintf("%s:%d", config.Address, config.Port),
		Handler:      ws.basicAuth(mux),
		ReadTimeout:  30 * time.Second,
		WriteTimeout: 30 * time.Second,
	}

	return ws, nil
}

// Start begins the web server
func (ws *WebServer) Start() {
	log.Printf("Starting web server on %s", ws.server.Addr)

	var err error
	if ws.config.CertFile != "" && ws.config.KeyFile != "" {
		err = ws.server.ListenAndServeTLS(ws.config.CertFile, ws.config.KeyFile)
	} else {
		err = ws.server.ListenAndServe()
	}

	if err != http.ErrServerClosed {
		log.Printf("Web server error: %v", err)
	}
}

// Stop shuts down the web server
func (ws *WebServer) Stop() {
	if ws.server != nil {
		ws.server.Close()
	}
}

// basicAuth provides basic HTTP authentication
func (ws *WebServer) basicAuth(next http.Handler) http.Handler {
	if ws.config.Username == "" {
		return next
	}

	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		username, password, ok := r.BasicAuth()
		if !ok || username != ws.config.Username || password != ws.config.Password {
			w.Header().Set("WWW-Authenticate", `Basic realm="Login Server"`)
			w.WriteHeader(http.StatusUnauthorized)
			w.Write([]byte("Unauthorized"))
			return
		}
		next.ServeHTTP(w, r)
	})
}

// handleStatus returns server status information
func (ws *WebServer) handleStatus(w http.ResponseWriter, r *http.Request) {
	stats := ws.loginServer.GetStats()

	status := map[string]any{
		"service":    "eq2emu-login-server",
		"version":    "1.0.0",
		"status":     "running",
		"timestamp":  time.Now().UTC(),
		"statistics": stats,
	}

	ws.writeJSON(w, status)
}

// handleWorlds returns world server information
func (ws *WebServer) handleWorlds(w http.ResponseWriter, r *http.Request) {
	worlds := ws.loginServer.worldList.GetActiveWorlds()
	worldStats := ws.loginServer.worldList.GetStats()

	response := map[string]any{
		"world_servers": worlds,
		"statistics":    worldStats,
	}

	ws.writeJSON(w, response)
}

// handleStats returns detailed server statistics
func (ws *WebServer) handleStats(w http.ResponseWriter, r *http.Request) {
	serverStats := ws.loginServer.GetStats()
	worldStats := ws.loginServer.worldList.GetStats()

	stats := map[string]any{
		"server":    serverStats,
		"worlds":    worldStats,
		"timestamp": time.Now().UTC(),
	}

	ws.writeJSON(w, stats)
}

// handleHealth returns basic health check
func (ws *WebServer) handleHealth(w http.ResponseWriter, r *http.Request) {
	health := map[string]any{
		"status":    "healthy",
		"timestamp": time.Now().UTC(),
	}

	ws.writeJSON(w, health)
}

// writeJSON writes JSON response with proper headers
func (ws *WebServer) writeJSON(w http.ResponseWriter, data any) {
	w.Header().Set("Content-Type", "application/json")
	w.Header().Set("Cache-Control", "no-cache")

	if err := json.NewEncoder(w).Encode(data); err != nil {
		log.Printf("JSON encoding error: %v", err)
		http.Error(w, "Internal Server Error", http.StatusInternalServerError)
	}
}
