package infra

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

// HttpPostJSON realiza un POST request con body JSON y parsea la respuesta como JSON.
// Agrega Content-Type: application/json y Accept: application/json automaticamente.
// Retorna error si status >= 400 incluyendo status code y los primeros 200 bytes del body.
func HttpPostJSON(url string, body any, headers map[string]string, timeout time.Duration) (map[string]any, error) {
	data, err := json.Marshal(body)
	if err != nil {
		return nil, fmt.Errorf("http_post_json: marshal body: %w", err)
	}

	client := &http.Client{Timeout: timeout}

	req, err := http.NewRequest(http.MethodPost, url, bytes.NewReader(data))
	if err != nil {
		return nil, fmt.Errorf("http_post_json: build request: %w", err)
	}

	req.Header.Set("Content-Type", "application/json")
	req.Header.Set("Accept", "application/json")
	for k, v := range headers {
		req.Header.Set(k, v)
	}

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

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

	if resp.StatusCode >= 400 {
		preview := respBody
		if len(preview) > 200 {
			preview = preview[:200]
		}
		shortURL := url
		if len(shortURL) > 100 {
			shortURL = shortURL[:100]
		}
		return nil, fmt.Errorf("http_post_json: HTTP %d at %q — %s", resp.StatusCode, shortURL, preview)
	}

	var result map[string]any
	if err := json.Unmarshal(respBody, &result); err != nil {
		return nil, fmt.Errorf("http_post_json: parse JSON: %w", err)
	}

	return result, nil
}
