package infra

import (
	"bytes"
	"encoding/json"
	"mime/multipart"
	"net/http"
	"net/http/httptest"
	"testing"
)

// buildPNGMultipart crea un multipart con un campo "file" cuyo contenido tiene
// los magic bytes de PNG (suficientes para que FileValidateType los reconozca).
func buildPNGMultipart(t *testing.T, filename string, body string) (string, *bytes.Buffer) {
	t.Helper()
	var buf bytes.Buffer
	w := multipart.NewWriter(&buf)
	part, err := w.CreateFormFile("file", filename)
	if err != nil {
		t.Fatalf("CreateFormFile: %v", err)
	}
	// Magic bytes PNG: 89 50 4E 47 0D 0A 1A 0A
	part.Write([]byte{0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A})
	part.Write([]byte(body))
	w.Close()
	return w.FormDataContentType(), &buf
}

func TestUploadHandler(t *testing.T) {
	t.Run("acepta upload con imagen y responde JSON", func(t *testing.T) {
		dir := t.TempDir()
		cfg := StorageConfig{
			BaseDir:      dir,
			MaxFileSize:  1 << 20,
			AllowedTypes: []string{"image/png"},
		}
		ct, body := buildPNGMultipart(t, "foto.png", "data extra")

		req := httptest.NewRequest("POST", "/upload", body)
		req.Header.Set("Content-Type", ct)
		rec := httptest.NewRecorder()

		UploadHandler(cfg).ServeHTTP(rec, req)

		if rec.Code != http.StatusOK {
			t.Fatalf("got %d, body=%s", rec.Code, rec.Body.String())
		}
		var resp struct {
			Files []UploadedFile `json:"files"`
		}
		if err := json.Unmarshal(rec.Body.Bytes(), &resp); err != nil {
			t.Fatalf("unmarshal: %v", err)
		}
		if len(resp.Files) != 1 {
			t.Fatalf("got %d files, want 1", len(resp.Files))
		}
		if resp.Files[0].ContentType != "image/png" {
			t.Errorf("got ContentType %q", resp.Files[0].ContentType)
		}
	})

	t.Run("rechaza tipo no permitido con 415", func(t *testing.T) {
		dir := t.TempDir()
		cfg := StorageConfig{
			BaseDir:      dir,
			MaxFileSize:  1 << 20,
			AllowedTypes: []string{"application/pdf"}, // PNG no en lista
		}
		ct, body := buildPNGMultipart(t, "foto.png", "x")

		req := httptest.NewRequest("POST", "/upload", body)
		req.Header.Set("Content-Type", ct)
		rec := httptest.NewRecorder()

		UploadHandler(cfg).ServeHTTP(rec, req)

		if rec.Code != http.StatusUnsupportedMediaType {
			t.Errorf("got %d, want 415", rec.Code)
		}
	})

	t.Run("rechaza body que excede MaxFileSize con 400", func(t *testing.T) {
		dir := t.TempDir()
		cfg := StorageConfig{
			BaseDir:      dir,
			MaxFileSize:  10, // muy pequeno
			AllowedTypes: []string{"image/png"},
		}
		ct, body := buildPNGMultipart(t, "foto.png", "muchos bytes extra para superar 10")

		req := httptest.NewRequest("POST", "/upload", body)
		req.Header.Set("Content-Type", ct)
		rec := httptest.NewRecorder()

		UploadHandler(cfg).ServeHTTP(rec, req)
		if rec.Code != http.StatusBadRequest {
			t.Errorf("got %d, want 400", rec.Code)
		}
	})
}
