package segments

import (
	"errors"
	"fmt"
	"testing"

	"github.com/jandedobbeleer/oh-my-posh/src/runtime"
	"github.com/stretchr/testify/assert"
)

func TestHaskell(t *testing.T) {
	cases := []struct {
		Case            string
		ExpectedString  string
		GhcVersion      string
		StackGhcVersion string
		StackGhcMode    string
		InStackPackage  bool
		StackGhc        bool
	}{
		{
			Case:            "GHC 8.10.7",
			ExpectedString:  "8.10.7",
			GhcVersion:      "8.10.7",
			StackGhcVersion: "9.0.2",
			StackGhcMode:    "never",
		},
		{
			Case:            "Stack GHC Mode - Always",
			ExpectedString:  "9.0.2",
			GhcVersion:      "8.10.7",
			StackGhcVersion: "9.0.2",
			StackGhcMode:    "always",
			StackGhc:        true,
		},
		{
			Case:            "Stack GHC Mode - Package",
			ExpectedString:  "9.0.2",
			GhcVersion:      "8.10.7",
			StackGhcVersion: "9.0.2",
			StackGhcMode:    "package",
			InStackPackage:  true,
			StackGhc:        true,
		},
		{
			Case:            "Stack GHC Mode - Package no stack.yaml",
			ExpectedString:  "8.10.7",
			GhcVersion:      "8.10.7",
			StackGhcVersion: "9.0.2",
			StackGhcMode:    "package",
		},
	}

	for _, tc := range cases {
		params := &mockedLanguageParams{
			cmd:           "ghc",
			versionParam:  "--numeric-version",
			versionOutput: tc.GhcVersion,
			extension:     "*.hs",
		}
		env, props := getMockedLanguageEnv(params)

		if tc.StackGhcMode == "always" || (tc.StackGhcMode == "package" && tc.InStackPackage) {
			env.On("HasCommand", "stack").Return(true)
			env.On("RunCommand", "stack", []string{"ghc", "--", "--numeric-version"}).Return(tc.StackGhcVersion, nil)
		}

		fileInfo := &runtime.FileInfo{
			Path:         "../stack.yaml",
			ParentFolder: "./",
			IsDir:        false,
		}

		if tc.InStackPackage {
			var err error
			env.On("HasParentFilePath", "stack.yaml", false).Return(fileInfo, err)
		} else {
			env.On("HasParentFilePath", "stack.yaml", false).Return(fileInfo, errors.New("no match"))
		}

		props[StackGhcMode] = tc.StackGhcMode

		h := &Haskell{}
		h.Init(props, env)

		failMsg := fmt.Sprintf("Failed in case: %s", tc.Case)
		assert.True(t, h.Enabled(), failMsg)
		assert.Equal(t, tc.ExpectedString, renderTemplate(env, h.Template(), h), failMsg)
		assert.Equal(t, tc.StackGhc, h.StackGhc, failMsg)
	}
}
