// Package soip is a small client for the IPSee commercial API.
package soip

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

type Client struct { APIKey, BaseURL string; HTTPClient *http.Client }

func New(apiKey, baseURL string) *Client {
	return &Client{APIKey: apiKey, BaseURL: strings.TrimRight(baseURL, "/"), HTTPClient: &http.Client{Timeout: 15 * time.Second}}
}

func (client *Client) request(ctx context.Context, method, path string, payload any) (map[string]any, error) {
	var body io.Reader
	if payload != nil { encoded, err := json.Marshal(payload); if err != nil { return nil, err }; body = bytes.NewReader(encoded) }
	request, err := http.NewRequestWithContext(ctx, method, client.BaseURL+path, body); if err != nil { return nil, err }
	request.Header.Set("x-api-key", client.APIKey); request.Header.Set("content-type", "application/json")
	response, err := client.HTTPClient.Do(request); if err != nil { return nil, err }; defer response.Body.Close()
	var result map[string]any; if err = json.NewDecoder(response.Body).Decode(&result); err != nil { return nil, err }
	if response.StatusCode < 200 || response.StatusCode >= 300 { return nil, fmt.Errorf("IPSee API returned %d: %v", response.StatusCode, result["message"]) }
	return result, nil
}

func (client *Client) Lookup(ctx context.Context, ip, lang string) (map[string]any, error) {
	return client.request(ctx, http.MethodGet, "/ip/"+url.PathEscape(ip)+"?lang="+url.QueryEscape(lang), nil)
}

func (client *Client) Batch(ctx context.Context, ips []string, lang string) (map[string]any, error) {
	return client.request(ctx, http.MethodPost, "/ip/batch", map[string]any{"ips": ips, "lang": lang})
}

func (client *Client) Account(ctx context.Context) (map[string]any, error) {
	return client.request(ctx, http.MethodGet, "/account", nil)
}
