package downloader_test

import (
	"net/http"
	"net/http/httptest"
	"os"
	"testing"

	"git.ar21.de/yolokube/country-geo-locations/internal/downloader"
)

// TestNewContext tests the creation of a new Context.
func TestNewContext(t *testing.T) {
	filename := "testfile"
	link := "http://example.com"
	ctx := downloader.NewContext(filename, link)

	if ctx.Filename != filename {
		t.Errorf("expected %s, got %s", filename, ctx.Filename)
	}
	if ctx.Link != link {
		t.Errorf("expected %s, got %s", link, ctx.Link)
	}
}

// TestDownload tests the Download function with different scenarios.
func TestDownload(t *testing.T) {
	t.Run("ValidDownload", func(t *testing.T) {
		// Mock server to simulate a valid download
		server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
			w.WriteHeader(http.StatusOK)
			w.Write([]byte("This is the file content"))
		}))
		defer server.Close()

		filename := "test_valid_download.txt"
		ctx := downloader.NewContext(filename, server.URL)
		defer os.Remove(filename)

		err := ctx.Download()
		if err != nil {
			t.Errorf("expected no error, got %v", err)
		}

		if !ctx.FileExists() {
			t.Errorf("expected file to exist, but it does not")
		}
	})

	t.Run("InvalidURL", func(t *testing.T) {
		ctx := downloader.NewContext("test_invalid_url.txt", "http://invalid.url")
		err := ctx.Download()

		if err == nil || err.Error() != "invalid url" {
			t.Errorf("expected invalid url error, got %v", err)
		}
	})

	t.Run("CertificateError", func(t *testing.T) {
		// This test assumes a self-signed certificate or similar issue. This is hard to simulate in a unit test.
		ctx := downloader.NewContext("test_cert_error.txt", "https://self-signed.badssl.com/") // Example URL that can be used

		if err := ctx.Download(); err == nil || err.Error() != "certificate from unknown authority" {
			t.Errorf("expected certificate from unknown authority error, got %v", err)
		}
	})

	t.Run("FileNotFound", func(t *testing.T) {
		// Mock server to simulate a 404 response
		server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
			w.WriteHeader(http.StatusNotFound)
		}))
		defer server.Close()

		ctx := downloader.NewContext("test_not_found.txt", server.URL)

		if err := ctx.Download(); err == nil || err.Error() != "invalid url" {
			t.Errorf("expected invalid url error, got %v", err)
		}
	})

	t.Run("RestrictedAccess", func(t *testing.T) {
		// Mock server to simulate a 401 response
		server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
			w.WriteHeader(http.StatusUnauthorized)
		}))
		defer server.Close()

		ctx := downloader.NewContext("test_restricted_access.txt", server.URL)

		if err := ctx.Download(); err == nil || err.Error() != "restricted access (credentials required)" {
			t.Errorf("expected restricted access error, got %v", err)
		}
	})
}

// TestFileExists tests the FileExists function.
func TestFileExists(t *testing.T) {
	filename := "testfile_exists.txt"
	ctx := downloader.NewContext(filename, "http://example.com")

	// Ensure file does not exist initially
	if ctx.FileExists() {
		t.Errorf("expected file to not exist, but it does")
	}

	// Create a file and check again
	file, err := os.Create(filename)
	if err != nil {
		t.Fatalf("failed to create test file: %v", err)
	}
	file.Close()
	defer os.Remove(filename)

	if !ctx.FileExists() {
		t.Errorf("expected file to exist, but it does not")
	}
}