package services

import (
	"fmt"
	"log"
	"math/rand"
	"net/http"
	"sync"
	"time"

	"github.com/gorilla/websocket"
)

type WebRTCService struct {
	rooms    map[string]*WebRTCRoom
	roomsMux sync.RWMutex
	upgrader websocket.Upgrader
}

type WebRTCRoom struct {
	Code      string
	Sender    *WebRTCClient
	Receiver  *WebRTCClient
	CreatedAt time.Time
	ExpiresAt time.Time      // 添加过期时间
	LastOffer *WebRTCMessage // 保存最后的offer消息
}

type WebRTCClient struct {
	ID         string
	Role       string // "sender" or "receiver"
	Connection *websocket.Conn
	Room       string
}

func NewWebRTCService() *WebRTCService {
	service := &WebRTCService{
		rooms:    make(map[string]*WebRTCRoom),
		roomsMux: sync.RWMutex{},
		upgrader: websocket.Upgrader{
			CheckOrigin: func(r *http.Request) bool {
				return true // 允许所有来源，生产环境应当限制
			},
		},
	}

	// 启动房间清理任务
	go service.cleanupExpiredRooms()

	return service
}

type WebRTCMessage struct {
	Type    string      `json:"type"`
	From    string      `json:"from"`
	To      string      `json:"to"`
	Payload interface{} `json:"payload"`
}

// HandleWebSocket 处理WebRTC信令WebSocket连接
func (ws *WebRTCService) HandleWebSocket(w http.ResponseWriter, r *http.Request) {
	log.Printf("收到WebRTC WebSocket连接请求: %s", r.URL.String())

	conn, err := ws.upgrader.Upgrade(w, r, nil)
	if err != nil {
		log.Printf("WebRTC WebSocket升级失败: %v", err)
		return
	}
	defer conn.Close()

	// 获取房间码和角色
	code := r.URL.Query().Get("code")
	role := r.URL.Query().Get("role")

	log.Printf("WebRTC连接参数: code=%s, role=%s", code, role)

	if code == "" || (role != "sender" && role != "receiver") {
		log.Printf("WebRTC连接参数无效: code=%s, role=%s", code, role)
		return
	}

	// 生成客户端ID
	clientID := ws.generateClientID()
	client := &WebRTCClient{
		ID:         clientID,
		Role:       role,
		Connection: conn,
		Room:       code,
	}

	log.Printf("WebRTC客户端已创建: ID=%s, Role=%s, Room=%s", clientID, role, code)

	// 添加客户端到房间
	ws.addClientToRoom(code, client)
	log.Printf("WebRTC %s连接到房间: %s (客户端ID: %s)", role, code, clientID)

	// 连接关闭时清理
	defer func() {
		ws.removeClientFromRoom(code, clientID)
		log.Printf("WebRTC客户端断开连接: %s (房间: %s)", clientID, code)

		// 通知房间内其他客户端对方已断开连接
		ws.notifyRoomDisconnection(code, clientID, client.Role)
	}()

	// 处理消息
	for {
		var msg WebRTCMessage
		err := conn.ReadJSON(&msg)
		if err != nil {
			log.Printf("读取WebRTC WebSocket消息失败: %v", err)
			break
		}

		msg.From = clientID
		log.Printf("收到WebRTC信令: 类型=%s, 来自=%s, 房间=%s", msg.Type, clientID, code)

		// 转发信令消息给对方
		ws.forwardMessage(code, clientID, &msg)
	}
}

// 添加客户端到房间
func (ws *WebRTCService) addClientToRoom(code string, client *WebRTCClient) {
	ws.roomsMux.Lock()
	defer ws.roomsMux.Unlock()

	room := ws.rooms[code]
	if room == nil {
		room = &WebRTCRoom{
			Code:      code,
			CreatedAt: time.Now(),
			ExpiresAt: time.Now().Add(time.Hour), // 1小时后过期
		}
		ws.rooms[code] = room
		log.Printf("自动创建WebRTC房间: %s", code)
	}

	if client.Role == "sender" {
		room.Sender = client
	} else {
		room.Receiver = client
		// 如果接收方连接，且有保存的offer，立即发送给接收方
		if room.LastOffer != nil {
			log.Printf("向新连接的接收方发送保存的offer")
			err := client.Connection.WriteJSON(room.LastOffer)
			if err != nil {
				log.Printf("发送保存的offer失败: %v", err)
			}
		}
	}
}

// 从房间移除客户端
func (ws *WebRTCService) removeClientFromRoom(code string, clientID string) {
	ws.roomsMux.Lock()
	defer ws.roomsMux.Unlock()

	room := ws.rooms[code]
	if room == nil {
		return
	}

	if room.Sender != nil && room.Sender.ID == clientID {
		room.Sender = nil
	}
	if room.Receiver != nil && room.Receiver.ID == clientID {
		room.Receiver = nil
	}

	// 如果房间为空，删除房间
	if room.Sender == nil && room.Receiver == nil {
		delete(ws.rooms, code)
		log.Printf("清理WebRTC房间: %s", code)
	}
}

// 转发信令消息
func (ws *WebRTCService) forwardMessage(roomCode string, fromClientID string, msg *WebRTCMessage) {
	ws.roomsMux.Lock()
	defer ws.roomsMux.Unlock()

	room := ws.rooms[roomCode]
	if room == nil {
		return
	}

	// 如果是offer消息，保存起来
	if msg.Type == "offer" {
		room.LastOffer = msg
		log.Printf("保存offer消息，等待接收方连接")
	}

	var targetClient *WebRTCClient
	if room.Sender != nil && room.Sender.ID == fromClientID {
		// 消息来自sender，转发给receiver
		targetClient = room.Receiver
	} else if room.Receiver != nil && room.Receiver.ID == fromClientID {
		// 消息来自receiver，转发给sender
		targetClient = room.Sender
	}

	if targetClient != nil && targetClient.Connection != nil {
		msg.To = targetClient.ID
		err := targetClient.Connection.WriteJSON(msg)
		if err != nil {
			log.Printf("转发WebRTC信令失败: %v", err)
		} else {
			log.Printf("转发WebRTC信令: 类型=%s, 从=%s到=%s", msg.Type, fromClientID, targetClient.ID)
		}
	} else {
		log.Printf("目标客户端不在线，消息类型=%s", msg.Type)
	}
}

// CreateRoom 创建或获取房间
func (ws *WebRTCService) CreateRoom(code string) {
	ws.roomsMux.Lock()
	defer ws.roomsMux.Unlock()

	if _, exists := ws.rooms[code]; !exists {
		ws.rooms[code] = &WebRTCRoom{
			Code:      code,
			CreatedAt: time.Now(),
			ExpiresAt: time.Now().Add(time.Hour), // 1小时后过期
		}
		log.Printf("创建WebRTC房间: %s", code)
	}
}

// CreateNewRoom 创建新房间并返回房间码
func (ws *WebRTCService) CreateNewRoom() string {
	code := ws.generatePickupCode()
	ws.CreateRoom(code)
	return code
}

// generatePickupCode 生成6位取件码
func (ws *WebRTCService) generatePickupCode() string {
	source := rand.NewSource(time.Now().UnixNano())
	rng := rand.New(source)
	code := rng.Intn(900000) + 100000
	return fmt.Sprintf("%d", code)
}

// cleanupExpiredRooms 定期清理过期房间
func (ws *WebRTCService) cleanupExpiredRooms() {
	ticker := time.NewTicker(5 * time.Minute)
	defer ticker.Stop()

	for range ticker.C {
		ws.roomsMux.Lock()
		now := time.Now()
		for code, room := range ws.rooms {
			// 房间过期或无客户端连接则删除
			if now.After(room.ExpiresAt) || (room.Sender == nil && room.Receiver == nil) {
				delete(ws.rooms, code)
				log.Printf("清理过期WebRTC房间: %s", code)
			}
		}
		ws.roomsMux.Unlock()
	}
}

// generateClientID 生成客户端ID
func (ws *WebRTCService) generateClientID() string {
	return fmt.Sprintf("webrtc_client_%d", rand.Int63())
}

// 通知房间内客户端有人断开连接
func (ws *WebRTCService) notifyRoomDisconnection(roomCode string, disconnectedClientID string, disconnectedRole string) {
	ws.roomsMux.Lock()
	defer ws.roomsMux.Unlock()

	room := ws.rooms[roomCode]
	if room == nil {
		return
	}

	// 构建断开连接通知消息
	disconnectionMsg := &WebRTCMessage{
		Type: "disconnection",
		From: disconnectedClientID,
		Payload: map[string]interface{}{
			"role":    disconnectedRole,
			"message": "对方已停止传输",
		},
	}

	// 通知房间内其他客户端
	if room.Sender != nil && room.Sender.ID != disconnectedClientID {
		err := room.Sender.Connection.WriteJSON(disconnectionMsg)
		if err != nil {
			log.Printf("通知发送方断开连接失败: %v", err)
		} else {
			log.Printf("已通知发送方: 对方已断开连接")
		}
	}

	if room.Receiver != nil && room.Receiver.ID != disconnectedClientID {
		err := room.Receiver.Connection.WriteJSON(disconnectionMsg)
		if err != nil {
			log.Printf("通知接收方断开连接失败: %v", err)
		} else {
			log.Printf("已通知接收方: 对方已断开连接")
		}
	}
}
func (ws *WebRTCService) GetRoomStatus(code string) map[string]interface{} {
	ws.roomsMux.RLock()
	defer ws.roomsMux.RUnlock()

	room := ws.rooms[code]
	if room == nil {
		return map[string]interface{}{
			"success": false,
			"exists":  false,
			"message": "房间不存在或已过期",
		}
	}

	return map[string]interface{}{
		"success":         true,
		"exists":          true,
		"sender_online":   room.Sender != nil,
		"receiver_online": room.Receiver != nil,
		"created_at":      room.CreatedAt,
	}
}
