package infra

import (
	"net/http"
	"net/http/httptest"
	"os"
	"path/filepath"
	"testing"
	"time"
)

func TestHttpDownloadFile(t *testing.T) {
	t.Run("httptest.Server sirve archivo binario", func(t *testing.T) {
		content := []byte("\x00\x01\x02\x03binary content")
		srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			w.Header().Set("Content-Type", "application/octet-stream")
			w.Write(content)
		}))
		defer srv.Close()

		tmp := t.TempDir()
		dest := filepath.Join(tmp, "out.bin")

		n, err := HttpDownloadFile(srv.URL, dest, nil, 5*time.Second)
		if err != nil {
			t.Fatalf("unexpected error: %v", err)
		}
		if n != int64(len(content)) {
			t.Errorf("got %d bytes, want %d", n, len(content))
		}
		got, _ := os.ReadFile(dest)
		if string(got) != string(content) {
			t.Errorf("file content mismatch")
		}
	})

	t.Run("Directorio creado automaticamente", func(t *testing.T) {
		srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			w.Write([]byte("data"))
		}))
		defer srv.Close()

		tmp := t.TempDir()
		dest := filepath.Join(tmp, "nested", "deep", "file.bin")

		_, err := HttpDownloadFile(srv.URL, dest, nil, 5*time.Second)
		if err != nil {
			t.Fatalf("unexpected error: %v", err)
		}
		if _, err := os.Stat(dest); os.IsNotExist(err) {
			t.Error("dest file does not exist after download")
		}
	})

	t.Run("Archivo temporal + rename (no deja basura si falla)", func(t *testing.T) {
		// Server que falla a mitad de la transferencia cortando la conexion
		srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			w.Write([]byte("partial"))
			// hijack y cierra bruscamente no disponible facilmente; simulamos con
			// status 500 antes de escribir
		}))
		defer srv.Close()

		// Verificar que un download exitoso no deja .download-* temporales
		tmp := t.TempDir()
		dest := filepath.Join(tmp, "file.bin")

		HttpDownloadFile(srv.URL, dest, nil, 5*time.Second)

		entries, _ := os.ReadDir(tmp)
		for _, e := range entries {
			if e.Name() != "file.bin" && filepath.Ext(e.Name()) != ".bin" {
				t.Errorf("unexpected temp file left: %s", e.Name())
			}
		}
	})

	t.Run("Size retornado coincide", func(t *testing.T) {
		content := make([]byte, 10000)
		for i := range content {
			content[i] = byte(i % 256)
		}
		srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			w.Write(content)
		}))
		defer srv.Close()

		tmp := t.TempDir()
		dest := filepath.Join(tmp, "big.bin")

		n, err := HttpDownloadFile(srv.URL, dest, nil, 5*time.Second)
		if err != nil {
			t.Fatalf("unexpected error: %v", err)
		}
		if n != int64(len(content)) {
			t.Errorf("got %d bytes, want %d", n, len(content))
		}
	})
}
