package action_test

import (
	. "github.com/onsi/ginkgo/v2"
	. "github.com/onsi/gomega"

	bosherrors "github.com/cloudfoundry/bosh-utils/errors"
	boshlog "github.com/cloudfoundry/bosh-utils/logger"

	"github.com/cloudfoundry/bosh-agent/v2/agent/action"
	"github.com/cloudfoundry/bosh-agent/v2/platform/platformfakes"
	boshsettings "github.com/cloudfoundry/bosh-agent/v2/settings"
	fakesettings "github.com/cloudfoundry/bosh-agent/v2/settings/fakes"
)

var _ = Describe("ListDisk", func() {
	var (
		settingsService *fakesettings.FakeSettingsService
		platform        *platformfakes.FakePlatform
		logger          boshlog.Logger
		listDiskAction  action.ListDiskAction
	)

	BeforeEach(func() {
		settingsService = &fakesettings.FakeSettingsService{}
		platform = &platformfakes.FakePlatform{}
		logger = boshlog.NewLogger(boshlog.LevelNone)
		listDiskAction = action.NewListDisk(settingsService, platform, logger)

		platform.IsPersistentDiskMountedStub = func(settings boshsettings.DiskSettings) (bool, error) {
			if settings.Path == "/dev/sdb" || settings.Path == "/dev/sdc" {
				return true, nil
			}

			return false, nil
		}
	})

	AssertActionIsSynchronousForVersion(listDiskAction, 1)
	AssertActionIsSynchronousForVersion(listDiskAction, 2)
	AssertActionIsAsynchronousForVersion(listDiskAction, 3)

	AssertActionIsNotPersistent(listDiskAction)
	AssertActionIsLoggable(listDiskAction)

	AssertActionIsNotResumable(listDiskAction)
	AssertActionIsNotCancelable(listDiskAction)

	Context("list disk run", func() {
		Context("persistent disks defined", func() {
			BeforeEach(func() {
				platform.IsPersistentDiskMountedStub = func(diskSettings boshsettings.DiskSettings) (bool, error) {
					expectedHints := []string{"/dev/sdb", "/dev/sdc", "abc", "def"}
					for _, mountedPath := range expectedHints {
						if mountedPath == diskSettings.Path {
							return true, nil
						}
					}
					return false, nil

				}

				settingsService.PersistentDiskSettings = map[string]boshsettings.DiskSettings{
					"1": {ID: "1", Path: "/dev/sdb"},
					"2": {ID: "2", Path: "/dev/sdc"},
					"3": {ID: "3", Path: "abc"},
					"4": {ID: "4", Path: "def"},
					"5": {ID: "5", Path: "xyz"},
				}
			})

			It("returns list of mounted disks", func() {
				value, err := listDiskAction.Run()
				Expect(err).ToNot(HaveOccurred())
				values, ok := value.([]string)
				Expect(ok).To(BeTrue())
				Expect(values).To(ContainElement("1"))
				Expect(values).To(ContainElement("2"))
				Expect(values).To(ContainElement("3"))
				Expect(values).To(ContainElement("4"))
				Expect(values).ToNot(ContainElement("5"))
			})
		})

		Context("there are no disks", func() {
			It("returns an empty array", func() {
				result, err := listDiskAction.Run()
				Expect(err).ToNot(HaveOccurred())
				Expect(result).ToNot(BeNil())
				Expect(result).To(Equal(make([]string, 0)))
			})
		})
	})

	Context("error loading disk paths", func() {
		Context("when unable to loadsettings", func() {
			It("should return an error", func() {
				settingsService.LoadSettingsError = bosherrors.Error("fake loadsettings error")

				_, err := listDiskAction.Run()
				Expect(err).To(HaveOccurred())
				Expect(err.Error()).To(ContainSubstring("Refreshing the settings: fake loadsettings error"))
			})
		})

		Context("when unable to load persistent disk hints", func() {
			Context("when persistent disk settings file does not exist", func() {
				It("should not return an error", func() {
					_, err := listDiskAction.Run()
					Expect(err).ToNot(HaveOccurred())
				})
			})

			Context("when getting disk hint settings fails", func() {
				It("should return an error", func() {
					settingsService.GetAllPersistentDiskSettingsError = bosherrors.Error("fake get persistent disk hints error")

					_, err := listDiskAction.Run()
					Expect(err).To(HaveOccurred())
					Expect(err.Error()).To(ContainSubstring("Getting persistent disk settings: fake get persistent disk hints error"))
				})
			})
		})
	})
})
