package chat

import (
	"context"
	"fmt"
	"strconv"

	"juwan-backend/app/chat/chatcore"

	"github.com/wwweww/go-wst/protocol"
)

func (h *Handler) handleJoin(conn protocol.Connection, msg *WsMessage) error {
	uid := h.getUserId(conn)
	if uid <= 0 {
		return conn.SendJSON(context.Background(), WsResponse{
			Type:    "error",
			Content: "authentication required",
		})
	}
	if msg.SessionId <= 0 {
		return conn.SendJSON(context.Background(), WsResponse{
			Type:    "error",
			Content: "sessionId is required",
		})
	}

	session, err := h.svcCtx.Store.GetSession(msg.SessionId)
	if err != nil {
		return conn.SendJSON(context.Background(), WsResponse{
			Type:    "error",
			Content: "session not found",
		})
	}

	isMember := false
	for _, p := range session.Participants {
		if p == uid {
			isMember = true
			break
		}
	}
	if !isMember {
		return conn.SendJSON(context.Background(), WsResponse{
			Type:    "error",
			Content: "not a member of this session",
		})
	}

	conn.SetMetadata("sessionId", msg.SessionId)

	h.broadcastToParticipants(session.Participants, WsResponse{
		Type:      "user_joined",
		SessionId: msg.SessionId,
		SenderId:  uid,
		Content:   fmt.Sprintf("user %d joined", uid),
	})

	return conn.SendJSON(context.Background(), WsResponse{
		Type:      "joined",
		SessionId: msg.SessionId,
	})
}

func (h *Handler) handleLeave(conn protocol.Connection, msg *WsMessage) error {
	uid := h.getUserId(conn)
	sessionId := msg.SessionId
	if sessionId <= 0 {
		if sid, ok := conn.Metadata()["sessionId"].(int64); ok {
			sessionId = sid
		}
	}
	if sessionId <= 0 {
		return nil
	}

	session, err := h.svcCtx.Store.GetSession(sessionId)
	if err == nil {
		h.broadcastToParticipants(session.Participants, WsResponse{
			Type:      "user_left",
			SessionId: sessionId,
			SenderId:  uid,
			Content:   fmt.Sprintf("user %d left", uid),
		})
	}

	return nil
}

func (h *Handler) handleMessage(conn protocol.Connection, msg *WsMessage) error {
	uid := h.getUserId(conn)
	if uid <= 0 {
		return conn.SendJSON(context.Background(), WsResponse{
			Type:    "error",
			Content: "authentication required",
		})
	}

	sessionId := msg.SessionId
	if sessionId <= 0 {
		if sid, ok := conn.Metadata()["sessionId"].(int64); ok {
			sessionId = sid
		}
	}
	if sessionId <= 0 {
		return conn.SendJSON(context.Background(), WsResponse{
			Type:    "error",
			Content: "sessionId is required, join a session first",
		})
	}

	msgType := chatcore.MessageType(msg.MsgType)
	if msgType == "" {
		msgType = chatcore.MessageTypeText
	}

	chatMsg, err := h.svcCtx.Store.AddMessage(sessionId, uid, msgType, msg.Content)
	if err != nil {
		return conn.SendJSON(context.Background(), WsResponse{
			Type:    "error",
			Content: err.Error(),
		})
	}

	session, err := h.svcCtx.Store.GetSession(sessionId)
	if err != nil {
		return nil
	}

	outMsg := WsResponse{
		Type:      "message",
		SessionId: sessionId,
		SenderId:  uid,
		Content:   msg.Content,
		Data:      map[string]int64{"messageId": chatMsg.Id},
	}

	h.broadcastToParticipants(session.Participants, outMsg)

	for _, p := range session.Participants {
		if p == uid {
			continue
		}
		userIdStr := strconv.FormatInt(p, 10)
		if _, online := h.server.GetConnection(userIdStr); !online {
			h.storeOfflineMessage(userIdStr, outMsg)
		}
	}

	return nil
}

func (h *Handler) handleHistory(conn protocol.Connection, msg *WsMessage) error {
	uid := h.getUserId(conn)
	if uid <= 0 {
		return conn.SendJSON(context.Background(), WsResponse{
			Type:    "error",
			Content: "authentication required",
		})
	}
	if msg.SessionId <= 0 {
		return conn.SendJSON(context.Background(), WsResponse{
			Type:    "error",
			Content: "sessionId is required",
		})
	}

	session, err := h.svcCtx.Store.GetSession(msg.SessionId)
	if err != nil {
		return conn.SendJSON(context.Background(), WsResponse{
			Type:    "error",
			Content: "session not found",
		})
	}

	isMember := false
	for _, p := range session.Participants {
		if p == uid {
			isMember = true
			break
		}
	}
	if !isMember {
		return conn.SendJSON(context.Background(), WsResponse{
			Type:    "error",
			Content: "not a member of this session",
		})
	}

	messages := h.svcCtx.Store.GetMessages(msg.SessionId, 0, 50)

	return conn.SendJSON(context.Background(), WsResponse{
		Type:      "history",
		SessionId: msg.SessionId,
		Data:      messages,
	})
}
