package main

import (
	"log"
	"net/http"
	"sync"
	"time"

	"github.com/gin-gonic/gin"
	"github.com/gorilla/websocket"

	"mrcc/internal/config"
	"mrcc/internal/httpserver"
	"mrcc/internal/logger"
	"mrcc/pkg/response"
)

// === 数据结构骨架（对照开发文档 18.5 节）===

type RoomStatus string

const (
	RoomCreated  RoomStatus = "created"
	RoomWaiting  RoomStatus = "waiting"
	RoomPlaying  RoomStatus = "playing"
	RoomFinished RoomStatus = "finished"
)

// Player 玩家连接
type Player struct {
	UserID    string          `json:"user_id"`
	Username  string          `json:"username"`
	Conn      *websocket.Conn `json:"-"`
	IsReady   bool            `json:"is_ready"`
	JoinedAt  time.Time       `json:"joined_at"`
	SendQueue chan []byte      `json:"-"`
}

// Room 房间
type Room struct {
	ID          string             `json:"id"`
	Status      RoomStatus         `json:"status"`
	HostUserID  string             `json:"host_user_id"`
	MaxPlayers  int                `json:"max_players"`
	Players     map[string]*Player `json:"players"`
	CreatedAt   time.Time          `json:"created_at"`
	mu          sync.RWMutex       `json:"-"`
}

// RelayServer 中转服务器
type RelayServer struct {
	Rooms      map[string]*Room
	Players    map[string]*Player
	Register   chan *Player
	Unregister chan *Player
	mu         sync.RWMutex
}

func NewRelayServer() *RelayServer {
	return &RelayServer{
		Rooms:      make(map[string]*Room),
		Players:    make(map[string]*Player),
		Register:   make(chan *Player, 64),
		Unregister: make(chan *Player, 64),
	}
}

var upgrader = websocket.Upgrader{
	CheckOrigin: func(r *http.Request) bool {
		return true // 开发阶段允许所有来源
	},
}

// HandleWS 处理 WebSocket 连接升级
func HandleWS(relay *RelayServer) gin.HandlerFunc {
	return func(c *gin.Context) {
		userID := c.Query("user_id")
		if userID == "" {
			userID = "anonymous"
		}

		conn, err := upgrader.Upgrade(c.Writer, c.Request, nil)
		if err != nil {
			log.Printf("websocket upgrade failed: %v", err)
			return
		}

		player := &Player{
			UserID:    userID,
			Conn:      conn,
			JoinedAt:  time.Now(),
			SendQueue: make(chan []byte, 256),
		}

		relay.Register <- player

		log.Printf("player connected: %s", userID)

		// TODO: 实现读写 goroutine、房间管理、消息路由、断线重连
		// 当前骨架仅保持连接并读取消息
		go func() {
			defer func() {
				relay.Unregister <- player
				conn.Close()
			}()

			for {
				_, _, err := conn.ReadMessage()
				if err != nil {
					break
				}
			}
		}()
	}
}

func main() {
	cfg := config.Load("relay-server", "8086")
	logger.WithService(cfg.Name).Info("starting relay server", "port", cfg.Port)

	relay := NewRelayServer()

	// 后台处理注册/注销
	go func() {
		for {
			select {
			case player := <-relay.Register:
				relay.mu.Lock()
				relay.Players[player.UserID] = player
				relay.mu.Unlock()
				log.Printf("player registered: %s", player.UserID)

			case player := <-relay.Unregister:
				relay.mu.Lock()
				delete(relay.Players, player.UserID)
				relay.mu.Unlock()
				log.Printf("player unregistered: %s", player.UserID)
			}
		}
	}()

	srv := httpserver.New(cfg)

	// WebSocket 端点
	srv.GET("/ws", HandleWS(relay))

	// 房间信息端点（骨架）
	srv.GET("/rooms", func(c *gin.Context) {
		relay.mu.RLock()
		defer relay.mu.RUnlock()

		rooms := make([]gin.H, 0, len(relay.Rooms))
		for id, room := range relay.Rooms {
			rooms = append(rooms, gin.H{
				"id":          id,
				"status":      room.Status,
				"playerCount": len(room.Players),
			})
		}
		response.OK(c, gin.H{"rooms": rooms, "total": len(rooms)})
	})

	log.Printf("relay-server listening on %s (WS: /ws)", cfg.Address())
	if err := srv.Run(cfg.Address()); err != nil {
		log.Fatal(err)
	}
}
