package state

import (
	"errors"
	"strings"
	"sync"
	"testing"

	"go.uber.org/zap"

	"github.com/helmfile/helmfile/pkg/exectest"
	"github.com/helmfile/helmfile/pkg/helmexec"
)

func TestIsReleaseInstalled_HandlesConnectionError(t *testing.T) {
	logger := zap.NewNop().Sugar()

	state := &HelmState{
		logger: logger,
	}

	// Create a custom helm mock that fails on List operations
	helm := &CustomFailingHelm{
		Helm: &exectest.Helm{
			DiffMutex:     &sync.Mutex{},
			ChartsMutex:   &sync.Mutex{},
			ReleasesMutex: &sync.Mutex{},
		},
	}

	release := ReleaseSpec{
		Name:      "test-release",
		Chart:     "test/chart",
		Namespace: "default",
	}

	// This should return an error due to connection failure
	_, err := state.isReleaseInstalled(helmexec.HelmContext{}, helm, release)

	// Verify that error was propagated
	if err == nil {
		t.Fatalf("expected isReleaseInstalled to return error when Kubernetes is unreachable, but got no error")
	}

	if err.Error() == "" {
		t.Fatalf("expected isReleaseInstalled to return meaningful error when Kubernetes is unreachable, but got empty error")
	}

	// Check if the error contains the expected message
	expectedMsg := "Kubernetes cluster unreachable"
	if err.Error() != expectedMsg && !strings.Contains(err.Error(), "Kubernetes cluster unreachable") {
		t.Fatalf("expected error to contain 'Kubernetes cluster unreachable', but got: %v", err.Error())
	}
}

// CustomFailingHelm wraps exectest.Helm and overrides List to simulate failures
type CustomFailingHelm struct {
	*exectest.Helm
}

func (h *CustomFailingHelm) List(context helmexec.HelmContext, filter string, flags ...string) (string, error) {
	return "", errors.New("Kubernetes cluster unreachable: Get \"http://localhost:8080/version\": dial tcp [::1]:8080: connect: connection refused")
}
