package singlebase

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

type Result struct {
	Data     json.RawMessage `json:"data"`
	Error    map[string]any  `json:"error"`
	Meta     map[string]any  `json:"meta"`
	ExecTime *float64        `json:"exec_time"`
}

type Client struct {
	APIURL string
	APIKey string
	Bearer string
}

func (s Client) Call(ctx context.Context, operation string, payload map[string]any, options map[string]any) (Result, error) {
	body := map[string]any{"operation": operation, "payload": payload}
	if options != nil {
		body["options"] = options
	}
	raw, err := json.Marshal(body)
	if err != nil {
		return Result{}, err
	}
	req, err := http.NewRequestWithContext(ctx, "POST", s.APIURL, bytes.NewReader(raw))
	if err != nil {
		return Result{}, err
	}
	req.Header.Set("Content-Type", "application/json")
	req.Header.Set("X-API-KEY", s.APIKey)
	if s.Bearer != "" {
		req.Header.Set("Authorization", "Bearer "+s.Bearer)
	}
	httpClient := &http.Client{Timeout: 30 * time.Second}
	res, err := httpClient.Do(req)
	if err != nil {
		return Result{}, err
	}
	defer res.Body.Close()
	var result Result
	if err := json.NewDecoder(res.Body).Decode(&result); err != nil {
		return Result{}, err
	}
	if res.StatusCode >= 400 && result.Error == nil {
		return result, fmt.Errorf("HTTP %d without an API error envelope", res.StatusCode)
	}
	return result, nil
}
