package websocket

import (
	"encoding/json"
	"fmt"

	pb "git.solsynth.dev/goatworks/turbine/pkg/shared/proto/gen"
	"google.golang.org/protobuf/types/known/wrapperspb"
)

// WebSocketPacket represents a WebSocket message packet.
type WebSocketPacket struct {
	Type        string          `json:"type"`
	Data        json.RawMessage `json:"data,omitempty"` // Use json.RawMessage to delay deserialization
	Endpoint    string          `json:"endpoint,omitempty"`
	ErrorMessage string         `json:"error_message,omitempty"`
}

// ToBytes serializes the WebSocketPacket to a byte array for sending over WebSocket.
func (w *WebSocketPacket) ToBytes() ([]byte, error) {
	return json.Marshal(w)
}

// FromBytes deserializes a byte array into a WebSocketPacket.
func FromBytes(bytes []byte) (*WebSocketPacket, error) {
	var packet WebSocketPacket
	err := json.Unmarshal(bytes, &packet)
	if err != nil {
		return nil, fmt.Errorf("failed to deserialize WebSocketPacket: %w", err)
	}
	return &packet, nil
}

// GetData deserializes the Data property to the specified type T.
func (w *WebSocketPacket) GetData(v interface{}) error {
	if w.Data == nil {
		return nil
	}
	return json.Unmarshal(w.Data, v)
}

// ToProtoValue converts the WebSocketPacket to its protobuf equivalent.
func (w *WebSocketPacket) ToProtoValue() *pb.WebSocketPacket {
	var dataBytes []byte
	if w.Data != nil {
		dataBytes = w.Data
	}
	var errorMessage string
	if w.ErrorMessage != "" {
		errorMessage = w.ErrorMessage
	}
	return &pb.WebSocketPacket{
		Type:        w.Type,
		Data:        dataBytes,
		ErrorMessage: wrapperspb.String(errorMessage),
	}
}

// FromProtoValue converts a protobuf WebSocketPacket to its Go struct equivalent.
func FromProtoValue(packet *pb.WebSocketPacket) *WebSocketPacket {
	var data json.RawMessage
	if packet.Data != nil {
		data = json.RawMessage(packet.Data)
	}
	var errorMessage string
	if packet.ErrorMessage != nil {
		errorMessage = packet.ErrorMessage.GetValue()
	}

	return &WebSocketPacket{
		Type:        packet.Type,
		Data:        data,
		ErrorMessage: errorMessage,
	}
}

// WebSocketPacketType constants from C# example
const (
	WebSocketPacketTypePing  = "ping"
	WebSocketPacketTypePong  = "pong"
	WebSocketPacketTypeError = "error"
)
