package proxmox

import (
	"context"
	"encoding/json"
	"net/http"
	"net/http/httptest"
	"testing"
)

func TestListNetworks(t *testing.T) {
	// Create mock server
	mockServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		if r.URL.Path == "/api2/json/nodes/test-node/network" {
			networks := []Network{
				{Name: "vmbr0", Type: "bridge", Active: true, Address: "192.168.1.1/24"},
				{Name: "vmbr1", Type: "bridge", Active: true, Address: "10.0.0.1/24"},
				{Name: "eth0", Type: "eth", Active: true},
			}
			response := map[string]interface{}{
				"data": networks,
			}
			w.Header().Set("Content-Type", "application/json")
			json.NewEncoder(w).Encode(response)
		} else {
			w.WriteHeader(http.StatusNotFound)
		}
	}))
	defer mockServer.Close()

	// Create client with mock server
	httpClient := NewHTTPClient(mockServer.URL, true)
	client := &Client{
		httpClient: httpClient,
	}

	ctx := context.Background()
	networks, err := client.ListNetworks(ctx, "test-node")
	if err != nil {
		t.Fatalf("ListNetworks() error = %v", err)
	}

	if len(networks) != 3 {
		t.Errorf("ListNetworks() returned %d networks, want 3", len(networks))
	}

	// Check first network
	if networks[0].Name != "vmbr0" {
		t.Errorf("ListNetworks() first network name = %q, want vmbr0", networks[0].Name)
	}
	if networks[0].Type != "bridge" {
		t.Errorf("ListNetworks() first network type = %q, want bridge", networks[0].Type)
	}
}

func TestNetworkExists(t *testing.T) {
	tests := []struct {
		name         string
		networkName  string
		mockNetworks []Network
		expected     bool
		wantErr      bool
	}{
		{
			name:        "exists vmbr0",
			networkName: "vmbr0",
			mockNetworks: []Network{
				{Name: "vmbr0", Type: "bridge", Active: true},
				{Name: "vmbr1", Type: "bridge", Active: true},
			},
			expected: true,
			wantErr:  false,
		},
		{
			name:        "exists vmbr1",
			networkName: "vmbr1",
			mockNetworks: []Network{
				{Name: "vmbr0", Type: "bridge", Active: true},
				{Name: "vmbr1", Type: "bridge", Active: true},
			},
			expected: true,
			wantErr:  false,
		},
		{
			name:        "does not exist",
			networkName: "vmbr2",
			mockNetworks: []Network{
				{Name: "vmbr0", Type: "bridge", Active: true},
				{Name: "vmbr1", Type: "bridge", Active: true},
			},
			expected: false,
			wantErr:  false,
		},
		{
			name:        "empty network list",
			networkName: "vmbr0",
			mockNetworks: []Network{},
			expected:    false,
			wantErr:     false,
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			// Create mock server
			mockServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
				response := map[string]interface{}{
					"data": tt.mockNetworks,
				}
				w.Header().Set("Content-Type", "application/json")
				json.NewEncoder(w).Encode(response)
			}))
			defer mockServer.Close()

			// Create client
			httpClient := NewHTTPClient(mockServer.URL, true)
			client := &Client{
				httpClient: httpClient,
			}

			ctx := context.Background()
			exists, err := client.NetworkExists(ctx, "test-node", tt.networkName)
			if (err != nil) != tt.wantErr {
				t.Errorf("NetworkExists() error = %v, wantErr %v", err, tt.wantErr)
				return
			}
			if exists != tt.expected {
				t.Errorf("NetworkExists() = %v, want %v", exists, tt.expected)
			}
		})
	}
}

func TestNetworkExists_ErrorHandling(t *testing.T) {
	// Test with server that returns error
	mockServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.WriteHeader(http.StatusInternalServerError)
		w.Write([]byte("Internal Server Error"))
	}))
	defer mockServer.Close()

	httpClient := NewHTTPClient(mockServer.URL, true)
	client := &Client{
		httpClient: httpClient,
	}

	ctx := context.Background()
	exists, err := client.NetworkExists(ctx, "test-node", "vmbr0")
	if err == nil {
		t.Error("NetworkExists() expected error but got nil")
	}
	if exists {
		t.Error("NetworkExists() should return false on error")
	}
}

func TestListNetworks_ErrorHandling(t *testing.T) {
	// Test with server that returns error
	mockServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.WriteHeader(http.StatusNotFound)
		w.Write([]byte("Not Found"))
	}))
	defer mockServer.Close()

	httpClient := NewHTTPClient(mockServer.URL, true)
	client := &Client{
		httpClient: httpClient,
	}

	ctx := context.Background()
	networks, err := client.ListNetworks(ctx, "test-node")
	if err == nil {
		t.Error("ListNetworks() expected error but got nil")
	}
	if networks != nil && len(networks) > 0 {
		t.Error("ListNetworks() should return nil or empty slice on error")
	}
}

