package wsclient

import (
	"encoding/json"
	"log"
	"net/url"

	"git.lxtend.com/qqbot/constants"
	"git.lxtend.com/qqbot/handler"
	"git.lxtend.com/qqbot/model"
	"github.com/gorilla/websocket"
)

type WebSocketClient struct {
	conn *websocket.Conn
	done chan struct{}
}

func NewWebSocketClient(scheme, host, path string) (*WebSocketClient, error) {
	u := url.URL{Scheme: scheme, Host: host, Path: path}
	log.Printf("Connecting to %s", u.String())

	conn, _, err := websocket.DefaultDialer.Dial(u.String(), nil)
	if err != nil {
		return nil, err
	}

	client := &WebSocketClient{
		conn: conn,
		done: make(chan struct{}),
	}

	go client.receiveMessages()

	return client, nil
}

func (c *WebSocketClient) receiveMessages() {
	defer close(c.done)
	for {
		_, message, err := c.conn.ReadMessage()
		if err != nil {
			log.Println("Error reading message:", err)
			return
		}
		var event model.EventMessage
		if err = json.Unmarshal(message, &event); err != nil {
			log.Println("Error unmarshalling message:", err)
			return
		}
		msg := model.Message{
			UserId:       event.UserID,
			OriginMsgId:  event.MessageID,
			RawMsg:       event.RawMessage,
			UserNickName: event.Sender.Nickname,
		}

		if event.MessageType == constants.GROUP_MSG {
			msg.GroupInfo = model.GroupInfo{
				IsGroupMsg: true,
				GroupId:    event.GroupID,
				UserCard:   event.Sender.Card,
			}
		} else {
			msg.GroupInfo = model.GroupInfo{
				IsGroupMsg: false,
				GroupId:    event.Sender.GroupID,
			}
		}
		go func() {
			reply := handler.MsgInHandler(msg)
			if reply.ReplyMsg != "" {
				sendPkg := model.GenSendPkg(reply.FromMsg.UserId, reply.FromMsg.GroupInfo.GroupId, reply.ReplyMsg, false)
				sendPkgJson, err := json.Marshal(sendPkg)
				if err != nil {
					log.Println("Error marshalling sendPkg:", err)
					return
				}
				if err = c.SendMessage(websocket.TextMessage, sendPkgJson); err != nil {
					log.Println("Error sending message:", err)
					return
				}
			}
		}()
	}
}

func (c *WebSocketClient) SendMessage(messageType int, message []byte) error {
	return c.conn.WriteMessage(messageType, message)
}

func (c *WebSocketClient) Close() error {
	err := c.conn.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, ""))
	if err != nil {
		return err
	}
	<-c.done
	return c.conn.Close()
}
