package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"sync"
	"time"
)

// OpenClaw HTTP API client — uses the OpenAI-compatible /v1/chat/completions endpoint

type GatewayConfig struct {
	URL   string // http://host:port
	Token string
}

type GatewayPool struct {
	mu       sync.Mutex
	gateways map[string]*GatewayConfig
	client   *http.Client
}

func NewGatewayPool() *GatewayPool {
	return &GatewayPool{
		gateways: make(map[string]*GatewayConfig),
		client:   &http.Client{Timeout: 120 * time.Second},
	}
}

func (gp *GatewayPool) Register(host string, cfg *GatewayConfig) {
	gp.mu.Lock()
	defer gp.mu.Unlock()
	gp.gateways[host] = cfg
}

func (gp *GatewayPool) Get(host string) *GatewayConfig {
	gp.mu.Lock()
	defer gp.mu.Unlock()
	return gp.gateways[host]
}

// CallAgent sends a message (optionally with an image) to an agent via the OpenAI-compatible API.
// imageDataURL, if non-empty, should be a data URL: "data:image/png;base64,..."
func (gp *GatewayPool) CallAgent(host, agentID, message, session, imageDataURL string) (string, error) {
	cfg := gp.Get(host)
	if cfg == nil {
		return "", fmt.Errorf("no gateway configured for host %s", host)
	}

	// Build the message content — text only, or text + image
	var content any
	if imageDataURL != "" {
		content = []map[string]any{
			{"type": "text", "text": message},
			{"type": "image_url", "image_url": map[string]string{"url": imageDataURL}},
		}
	} else {
		content = message
	}

	body, _ := json.Marshal(map[string]any{
		"model": "openclaw:" + agentID,
		"user":  session,
		"messages": []map[string]any{
			{"role": "user", "content": content},
		},
	})

	req, err := http.NewRequest("POST", cfg.URL+"/v1/chat/completions", bytes.NewReader(body))
	if err != nil {
		return "", err
	}
	req.Header.Set("Content-Type", "application/json")
	req.Header.Set("Authorization", "Bearer "+cfg.Token)

	resp, err := gp.client.Do(req)
	if err != nil {
		return "", fmt.Errorf("http: %w", err)
	}
	defer resp.Body.Close()

	data, err := io.ReadAll(resp.Body)
	if err != nil {
		return "", fmt.Errorf("read body: %w", err)
	}

	if resp.StatusCode != 200 {
		return "", fmt.Errorf("http %d: %s", resp.StatusCode, string(data))
	}

	var result struct {
		Choices []struct {
			Message struct {
				Content string `json:"content"`
			} `json:"message"`
		} `json:"choices"`
	}
	if err := json.Unmarshal(data, &result); err != nil {
		return "", fmt.Errorf("parse: %w", err)
	}

	if len(result.Choices) == 0 || result.Choices[0].Message.Content == "" {
		return "[completed, no text reply]", nil
	}

	return result.Choices[0].Message.Content, nil
}
