package infra

import (
	"encoding/json"
	"io"
	"net/http"
	"net/http/httptest"
	"strings"
	"testing"
	"time"
)

func TestHttpPostJSON(t *testing.T) {
	t.Run("httptest.Server recibe body correcto", func(t *testing.T) {
		received := make(chan map[string]any, 1)
		srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			var body map[string]any
			data, _ := io.ReadAll(r.Body)
			json.Unmarshal(data, &body)
			received <- body
			w.Header().Set("Content-Type", "application/json")
			w.Write([]byte(`{"ok": true}`))
		}))
		defer srv.Close()

		_, err := HttpPostJSON(srv.URL, map[string]any{"name": "Alice", "score": 100}, nil, 5*time.Second)
		if err != nil {
			t.Fatalf("unexpected error: %v", err)
		}
		body := <-received
		if body["name"] != "Alice" {
			t.Errorf("name not received correctly, got: %v", body["name"])
		}
	})

	t.Run("Status 201 → exito", func(t *testing.T) {
		srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			w.Header().Set("Content-Type", "application/json")
			w.WriteHeader(http.StatusCreated)
			w.Write([]byte(`{"id": 42}`))
		}))
		defer srv.Close()

		result, err := HttpPostJSON(srv.URL, map[string]any{"x": 1}, nil, 5*time.Second)
		if err != nil {
			t.Fatalf("unexpected error: %v", err)
		}
		if result["id"] != float64(42) {
			t.Errorf("got id=%v, want 42", result["id"])
		}
	})

	t.Run("Status 500 → error con body parcial", func(t *testing.T) {
		srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			http.Error(w, "internal server error details", http.StatusInternalServerError)
		}))
		defer srv.Close()

		_, err := HttpPostJSON(srv.URL, map[string]any{}, nil, 5*time.Second)
		if err == nil {
			t.Fatal("expected error, got nil")
		}
		if !strings.Contains(err.Error(), "500") {
			t.Errorf("error should contain 500, got: %v", err)
		}
	})
}
