//go:build unix

package python

import (
	"context"
	"os"
	"os/exec"
	"path/filepath"
	"testing"

	"github.com/stretchr/testify/assert"
)

func TestAtLeastOnePythonInstalled(t *testing.T) {
	ctx := context.Background()
	all, err := DetectInterpreters(ctx)
	assert.NoError(t, err)
	a := all.Latest()
	t.Logf("latest is: %s", a)
	assert.True(t, len(all) > 0)
}

func TestNoInterpretersFound(t *testing.T) {
	t.Setenv("PATH", t.TempDir())

	ctx := context.Background()
	all, err := DetectInterpreters(ctx)
	assert.Nil(t, all)
	assert.Equal(t, ErrNoPythonInterpreters, err)
}

func TestFilteringInterpreters(t *testing.T) {
	rogueBin := filepath.Join(t.TempDir(), "rogue-bin")
	err := os.Mkdir(rogueBin, 0o777)
	assert.NoError(t, err)
	os.Chmod(rogueBin, 0o777)

	raw, err := os.ReadFile("testdata/world-writeable/python8.4")
	assert.NoError(t, err)

	injectedBinary := filepath.Join(rogueBin, "python8.4")
	err = os.WriteFile(injectedBinary, raw, 00777)
	assert.NoError(t, err)

	t.Setenv("PATH", "testdata/other-binaries-filtered:"+rogueBin)

	roguePath, err := exec.LookPath("python8.4")
	assert.NoError(t, err)
	assert.Equal(t, injectedBinary, roguePath)

	ctx := context.Background()
	all, err := DetectInterpreters(ctx)
	assert.NoError(t, err)
	assert.Len(t, all, 3)
	assert.Equal(t, "v2.7.18", all[0].Version)
	assert.Equal(t, "v3.10.5", all[1].Version)
	assert.Equal(t, "testdata/other-binaries-filtered/python3.10", all[1].Path)
	assert.Equal(t, "v3.11.4", all[2].Version)
	assert.Equal(t, "testdata/other-binaries-filtered/real-python3.11.4", all[2].Path)
}

func TestInterpretersAtLeastInvalidSemver(t *testing.T) {
	t.Setenv("PATH", "testdata/other-binaries-filtered")

	ctx := context.Background()
	all, err := DetectInterpreters(ctx)
	assert.NoError(t, err)

	_, err = all.AtLeast("v1.2.3.4")
	assert.EqualError(t, err, "invalid SemVer: v1.2.3.4")
}

func TestInterpretersAtLeast(t *testing.T) {
	t.Setenv("PATH", "testdata/other-binaries-filtered")

	ctx := context.Background()
	all, err := DetectInterpreters(ctx)
	assert.NoError(t, err)

	interpreter, err := all.AtLeast("3.10")
	assert.NoError(t, err)
	assert.Equal(t, "testdata/other-binaries-filtered/python3.10", interpreter.Path)
}

func TestInterpretersAtLeastNotSatisfied(t *testing.T) {
	t.Setenv("PATH", "testdata/other-binaries-filtered")

	ctx := context.Background()
	all, err := DetectInterpreters(ctx)
	assert.NoError(t, err)

	_, err = all.AtLeast("4.0.1")
	assert.EqualError(t, err, "cannot find Python greater or equal to v4.0.1")
}
