package main

import (
	_ "embed"
	"fmt"
	"log"
	"net/http"

	"github.com/gorilla/websocket"
)

//go:embed ui/index.html
var uiHTML string

var upgrader = websocket.Upgrader{CheckOrigin: func(r *http.Request) bool { return true }}

func startUI(dataDir, nodeID, serverAddr string) {
	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Content-Type", "text/html")
		fmt.Fprint(w, uiHTML)
	})

	http.HandleFunc("/ws", func(w http.ResponseWriter, r *http.Request) {
		conn, err := upgrader.Upgrade(w, r, nil)
		if err != nil {
			log.Printf("UI WS upgrade error: %v", err)
			return
		}
		defer conn.Close()
		log.Printf("UI client connected from %s", r.RemoteAddr)

		// Register notifier to forward activation results from main WS to this UI connection
		notifierID := registerUINotifier(func(msg map[string]interface{}) {
			log.Printf("UI notifier forwarding to browser: %+v", msg)
			if err := conn.WriteJSON(msg); err != nil {
				log.Printf("UI notify error: %v", err)
			} else {
				log.Printf("UI notifier sent successfully")
			}
		})
		defer unregisterUINotifier(notifierID)

		for {
			var msg map[string]interface{}
			if err := conn.ReadJSON(&msg); err != nil {
				log.Printf("UI client disconnected: %v", err)
				break
			}
			action, _ := msg["action"].(string)
			log.Printf("UI received action: %s", action)
			switch action {
			case "check":
				act, err := loadActivation(dataDir)
				if err == nil && act.Activated {
					conn.WriteJSON(map[string]interface{}{"action": "activated", "studentName": act.StudentName})
				} else {
					conn.WriteJSON(map[string]interface{}{"action": "not_activated"})
				}
			case "activate":
				code, _ := msg["code"].(string)
				log.Printf("UI handling activate with code: %s", code)
				if err := sendMessage(WSMessage{Action: "activate", NodeID: nodeID, Code: code}); err != nil {
					log.Printf("UI sendMessage failed: %v", err)
					conn.WriteJSON(map[string]interface{}{"action": "activation_failed", "error": err.Error()})
				} else {
					log.Printf("UI sendMessage succeeded, waiting for server response...")
				}
			case "instances":
				listInstances(dataDir, conn)
			}
		}
	})

	port := "7070"
	log.Printf("UI starting on http://localhost:%s", port)
	if err := http.ListenAndServe("127.0.0.1:"+port, nil); err != nil {
		log.Fatalf("UI server error: %v", err)
	}
}

func listInstances(dataDir string, conn *websocket.Conn) {
	instances, err := loadInstances(dataDir)
	if err != nil {
		log.Printf("loadInstances error: %v", err)
		conn.WriteJSON(map[string]interface{}{"action": "instances_list", "instances": []interface{}{}})
		return
	}

	var list []map[string]interface{}
	for _, inst := range instances {
		status := getInstanceStatus(dataDir, inst.ID)
		if status != inst.Status {
			inst.Status = status
			_ = upsertInstance(dataDir, inst)
		}
		list = append(list, map[string]interface{}{
			"id":           inst.ID,
			"templateName": inst.TemplateName,
			"port":         inst.Port,
			"status":       inst.Status,
			"url":          instanceURL(inst),
		})
	}

	conn.WriteJSON(map[string]interface{}{"action": "instances_list", "instances": list})
}
