package main

import (
	"context"
	"encoding/json"
	"fmt"
	"log"
	message "server/src/msg"
	"time"

	"github.com/gorilla/websocket"
	"google.golang.org/protobuf/proto"
)

const (
	ServerAddr = "ws://localhost:8081"
	Timeout    = 30 * time.Second
)

// WSClient 封装WebSocket客户端
type WSClient struct {
	conn *websocket.Conn
}

// Connect 连接到WebSocket服务器
func (c *WSClient) Connect() error {
	ctx, cancel := context.WithTimeout(context.Background(), Timeout)
	defer cancel()

	dialer := websocket.Dialer{
		HandshakeTimeout: Timeout,
	}

	conn, _, err := dialer.DialContext(ctx, ServerAddr, nil)
	if err != nil {
		return fmt.Errorf("failed to connect: %w", err)
	}

	c.conn = conn
	log.Println("Connected to server")
	return nil
}

// SendPacket 发送封包
func (c *WSClient) SendPacket(pkt Packet) error {
	data := EncodePacket(pkt)
	return c.conn.WriteMessage(websocket.BinaryMessage, data)
}

// ReceivePacket 接收封包
func (c *WSClient) ReceivePacket() (Packet, error) {
	_, data, err := c.conn.ReadMessage()
	if err != nil {
		return Packet{}, err
	}

	return DecodePacket(data)
}

// SendHeartbeat 发送心跳包
func (c *WSClient) SendHeartbeat() error {
	// 创建心跳消息
	heartbeat := &message.CS_Heartbeat{}
	data, err := proto.Marshal(heartbeat)
	if err != nil {
		return fmt.Errorf("failed to marshal heartbeat: %w", err)
	}

	// 创建封包 (假设心跳命令: main=1, sub=1)
	pkt := Packet{
		CmdMain: message.HEART,
		CmdSub:  message.CS_REQUEST,
		Data:    data,
	}

	return c.SendPacket(pkt)
}

// Login 发送登录请求
func (c *WSClient) Login(udid, passwd string, platform int32, version, device string) (*message.SC_User_Login, error) {
	// 创建登录请求
	loginReq := &message.CS_User_Login{
		Udid:          udid,
		Passwd:        passwd,
		Platform:      platform,
		ClientVersion: version,
		DeviceName:    device,
	}

	data, err := proto.Marshal(loginReq)
	if err != nil {
		return nil, fmt.Errorf("failed to marshal login request: %w", err)
	}

	// 创建封包 (假设登录命令: main=100, sub=1)
	pkt := Packet{
		CmdMain: message.USER,
		CmdSub:  message.CS_LOGIN,
		Data:    data,
	}

	// 发送登录请求
	if err := c.SendPacket(pkt); err != nil {
		return nil, fmt.Errorf("failed to send login request: %w", err)
	}

	// 接收响应
	respPkt, err := c.ReceivePacket()
	if err != nil {
		return nil, fmt.Errorf("failed to receive login response: %w", err)
	}

	// 解析登录响应
	loginResp := &message.SC_User_Login{}
	if err := proto.Unmarshal(respPkt.Data, loginResp); err != nil {
		return nil, fmt.Errorf("failed to unmarshal login response: %w", err)
	}

	return loginResp, nil
}

// StartHeartbeat 启动心跳循环
func (c *WSClient) StartHeartbeat(interval time.Duration) {
	ticker := time.NewTicker(interval)
	defer ticker.Stop()

	for {
		select {
		case <-ticker.C:
			if err := c.SendHeartbeat(); err != nil {
				log.Printf("Heartbeat failed: %v", err)
				return
			}
			log.Println("Heartbeat sent")
		}
	}
}

// Close 关闭连接
func (c *WSClient) Close() {
	if c.conn != nil {
		c.conn.Close()
		log.Println("Connection closed")
	}
}

// PrettyPrint 格式化输出Protobuf消息
func PrettyPrint(msg proto.Message) {
	jsonBytes, err := json.MarshalIndent(msg, "", "  ")
	if err != nil {
		log.Printf("Failed to marshal message: %v", err)
		return
	}
	fmt.Println(string(jsonBytes))
}
