package config

import (
	"testing"

	"github.com/stretchr/testify/require"
	"gopkg.in/yaml.v3"
)

func TestDefault(t *testing.T) {
	t.Parallel()

	conf := Default()

	require.Equal(t, ":9091", conf.RPCServer.Address)
	require.Equal(t, "/data/projects", conf.Services.Project.ProjectsRootDir)
	require.Equal(t, "/home/node/.codex", conf.Services.Project.CodexHomeDir)
	require.Contains(t, conf.Services.Project.DeniedDirectories, ".git")
	require.Equal(t, []string{"lost+found"}, conf.Services.Project.IgnoredProjectDirectories)
}

func TestServicesProjectYAML(t *testing.T) {
	t.Parallel()

	var conf RootConfig
	err := yaml.Unmarshal([]byte(`
rpcServer:
  address: :19091
services:
  project:
    projectsRootDir: /tmp/projects
    codexHomeDir: /tmp/codex-home
    gitBinary: /usr/bin/git
    maxEditableFileSize: 1024
    defaultPageSize: 20
    maxPageSize: 50
    maxPathLength: 512
    maxPathDepth: 8
    ignoredProjectDirectories: [lost+found, cache]
    deniedDirectories: [.git, node_modules]
`), &conf)

	require.NoError(t, err)
	require.Equal(t, "/tmp/projects", conf.Services.Project.ProjectsRootDir)
	require.Equal(t, 50, conf.Services.Project.MaxPageSize)
	require.Equal(t, []string{"lost+found", "cache"}, conf.Services.Project.IgnoredProjectDirectories)
}

func TestNormalizeAndValidate(t *testing.T) {
	t.Parallel()

	conf := Default()
	conf.Services.Project.ProjectsRootDir = "/tmp/projects"
	conf.Services.Project.CodexHomeDir = "/tmp/codex-home"
	conf.Services.Project.DeniedDirectories = []string{"node_modules", "node_modules"}
	conf.Services.Project.IgnoredProjectDirectories = []string{"lost+found", "cache", "lost+found"}

	conf.Normalize()

	require.Equal(t, []string{".git", "node_modules"}, conf.Services.Project.DeniedDirectories)
	require.Equal(t, []string{"cache", "lost+found"}, conf.Services.Project.IgnoredProjectDirectories)
	require.NoError(t, conf.Validate())
}

func TestNormalizeAppliesDefaultDeniedDirectories(t *testing.T) {
	t.Parallel()

	conf := RootConfig{}
	conf.Normalize()

	require.Contains(t, conf.Services.Project.DeniedDirectories, ".git")
	require.Contains(t, conf.Services.Project.DeniedDirectories, "node_modules")
	require.Equal(t, []string{"lost+found"}, conf.Services.Project.IgnoredProjectDirectories)
}

func TestValidateRejectsInvalidProjectConfig(t *testing.T) {
	t.Parallel()

	t.Run("relative root", func(t *testing.T) {
		conf := Default()
		conf.Services.Project.ProjectsRootDir = "projects"
		require.ErrorContains(t, conf.Validate(), "must be absolute")
	})

	t.Run("same roots", func(t *testing.T) {
		conf := Default()
		conf.Services.Project.ProjectsRootDir = "/tmp/root"
		conf.Services.Project.CodexHomeDir = "/tmp/root"
		require.ErrorContains(t, conf.Validate(), "must be different")
	})

	t.Run("invalid denylist entry", func(t *testing.T) {
		conf := Default()
		conf.Services.Project.DeniedDirectories = []string{"a/b"}
		require.ErrorContains(t, conf.Validate(), "one path segment")
	})

	t.Run("invalid ignored project directory", func(t *testing.T) {
		conf := Default()
		conf.Services.Project.IgnoredProjectDirectories = []string{"a/b"}
		require.ErrorContains(t, conf.Validate(), "one path segment")
	})
}
