// Package protocol définit le protocole de communication IPC via Unix sockets.
// Format: 4 bytes (big-endian length) + JSON payload
package protocol

import (
	"encoding/json"
	"time"
)

// Request représente une requête envoyée à un microservice.
type Request struct {
	ID        string         `json:"id"`
	Action    string         `json:"action"`
	TenantID  string         `json:"tenant_id,omitempty"`
	Params    map[string]any `json:"params,omitempty"`
	TimeoutMs int            `json:"timeout_ms,omitempty"`
}

// Response représente la réponse d'un microservice.
type Response struct {
	ID     string `json:"id"`
	Status string `json:"status"` // "success" ou "error"
	Result any    `json:"result,omitempty"`
	Error  *Error `json:"error,omitempty"`
}

// Error détaille une erreur.
type Error struct {
	Code    string `json:"code"`
	Message string `json:"message"`
}

// NewRequest crée une nouvelle requête avec un ID unique.
func NewRequest(action string, params map[string]any) *Request {
	return &Request{
		ID:        generateID(),
		Action:    action,
		Params:    params,
		TimeoutMs: 5000, // 5s par défaut
	}
}

// Success crée une réponse de succès.
func Success(reqID string, result any) *Response {
	return &Response{
		ID:     reqID,
		Status: "success",
		Result: result,
	}
}

// Failure crée une réponse d'erreur.
func Failure(reqID string, code, message string) *Response {
	return &Response{
		ID:     reqID,
		Status: "error",
		Error: &Error{
			Code:    code,
			Message: message,
		},
	}
}

// Encode sérialise un message en JSON.
func Encode(v any) ([]byte, error) {
	return json.Marshal(v)
}

// DecodeRequest désérialise une requête JSON.
func DecodeRequest(data []byte) (*Request, error) {
	var req Request
	if err := json.Unmarshal(data, &req); err != nil {
		return nil, err
	}
	return &req, nil
}

// DecodeResponse désérialise une réponse JSON.
func DecodeResponse(data []byte) (*Response, error) {
	var resp Response
	if err := json.Unmarshal(data, &resp); err != nil {
		return nil, err
	}
	return &resp, nil
}

// generateID génère un ID unique basé sur le timestamp.
func generateID() string {
	return "req_" + time.Now().Format("20060102150405.000000")
}
