// Package api 提供统一的API接口层
// 负责处理所有外部请求，包括HTTP和WebSocket接口
// 将请求路由到相应的服务层进行处理
package api

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

	"git.huangwc.com/pig/pig-farm-controller/internal/logs"
	"git.huangwc.com/pig/pig-farm-controller/internal/service"
	"github.com/gin-gonic/gin"
	"github.com/gorilla/websocket"
)

// WebSocket消息类型常量
const (
	// MessageTypeCommand 平台向设备发送的指令
	MessageTypeCommand = "command"

	// MessageTypeResponse 设备向平台发送的响应
	MessageTypeResponse = "response"

	// MessageTypeHeartbeat 心跳消息
	MessageTypeHeartbeat = "heartbeat"
)

// WebSocketMessage WebSocket消息结构
type WebSocketMessage struct {
	// Type 消息类型
	Type string `json:"type"`

	// DeviceID 设备ID
	DeviceID string `json:"device_id,omitempty"`

	// Command 指令内容
	Command string `json:"command,omitempty"`

	// Data 消息数据
	Data interface{} `json:"data,omitempty"`

	// Timestamp 时间戳
	Timestamp time.Time `json:"timestamp"`
}

// WebSocketManager WebSocket管理器
type WebSocketManager struct {
	// websocketService WebSocket服务
	websocketService *service.WebSocketService

	// logger 日志记录器
	logger *logs.Logger

	// upgrader WebSocket升级器
	upgrader websocket.Upgrader

	// mutex 互斥锁
	mutex sync.RWMutex

	// connections 设备连接映射
	connections map[string]*websocket.Conn
}

// NewWebSocketManager 创建WebSocket管理器实例
func NewWebSocketManager(websocketService *service.WebSocketService) *WebSocketManager {
	return &WebSocketManager{
		websocketService: websocketService,
		logger:           logs.NewLogger(),
		upgrader: websocket.Upgrader{
			CheckOrigin: func(r *http.Request) bool {
				// 允许所有跨域请求
				return true
			},
		},
		connections: make(map[string]*websocket.Conn),
	}
}

// HandleConnection 处理WebSocket连接
func (wm *WebSocketManager) HandleConnection(c *gin.Context) {
	// 升级HTTP连接到WebSocket
	conn, err := wm.upgrader.Upgrade(c.Writer, c.Request, nil)
	if err != nil {
		wm.logger.Error("WebSocket连接升级失败: " + err.Error())
		return
	}

	// 获取设备ID
	deviceID := c.Query("device_id")
	if deviceID == "" {
		wm.logger.Error("缺少设备ID参数")
		conn.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.ClosePolicyViolation, "缺少设备ID参数"))
		conn.Close()
		return
	}

	// 添加连接到映射
	wm.mutex.Lock()
	wm.connections[deviceID] = conn
	wm.mutex.Unlock()

	wm.logger.Info("设备 " + deviceID + " 已连接")

	// 发送连接成功消息
	successMsg := service.WebSocketMessage{
		Type:      "system",
		Command:   "connected",
		Timestamp: time.Now(),
	}
	conn.WriteJSON(successMsg)

	// 处理消息循环
	for {
		// 读取消息
		messageType, message, err := conn.ReadMessage()
		if err != nil {
			wm.logger.Error("读取设备 " + deviceID + " 消息失败: " + err.Error())
			break
		}

		// 只处理文本消息
		if messageType != websocket.TextMessage {
			continue
		}

		// 处理设备消息
		if err := wm.websocketService.HandleMessage(deviceID, message); err != nil {
			wm.logger.Error("处理设备 " + deviceID + " 消息失败: " + err.Error())
			continue
		}
	}

	// 连接断开时清理
	wm.mutex.Lock()
	delete(wm.connections, deviceID)
	wm.mutex.Unlock()

	conn.Close()
	wm.logger.Info("设备 " + deviceID + " 已断开连接")
}

// SendCommand 向指定设备发送指令
func (wm *WebSocketManager) SendCommand(deviceID, command string, data interface{}) error {
	wm.mutex.RLock()
	conn, exists := wm.connections[deviceID]
	wm.mutex.RUnlock()

	if !exists {
		return wm.websocketService.SendCommand(deviceID, command, data)
	}

	// 构造消息
	msg := service.WebSocketMessage{
		Type:      service.MessageTypeCommand,
		Command:   command,
		Data:      data,
		Timestamp: time.Now(),
	}

	// 发送消息
	if err := conn.WriteJSON(msg); err != nil {
		return err
	}

	return nil
}

// GetConnectedDevices 获取已连接的设备列表
func (wm *WebSocketManager) GetConnectedDevices() []string {
	wm.mutex.RLock()
	defer wm.mutex.RUnlock()

	devices := make([]string, 0, len(wm.connections))
	for deviceID := range wm.connections {
		devices = append(devices, deviceID)
	}

	return devices
}
