package config

import (
	"bytes"
	"os"
	"path/filepath"
	"testing"

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

func TestLoadAgentConfigTemplates(t *testing.T) {
	tests := []struct {
		name      string
		setup     func(t *testing.T, dir string)
		dirSuffix string
		wantErr   bool
		validate  func(t *testing.T, tmpl Templates)
	}{
		{
			name: "Success",
			setup: func(t *testing.T, dir string) {
				files := map[string]string{
					"root.yaml":            "root: {{.Value}}",
					"sub/child.yaml":       "child: {{.Value}}",
					"sub/nested/deep.yaml": "deep: {{.Value}}",
					"ignore.txt":           "should be ignored",
					"sub/ignore.json":      "{}",
				}
				createTestFiles(t, dir, files)
			},
			wantErr: false,
			validate: func(t *testing.T, tmpls Templates) {
				expectedKeys := []string{
					"root.yaml",
					"sub/child.yaml",
					"sub/nested/deep.yaml",
				}
				assert.Len(t, tmpls, len(expectedKeys))

				for _, key := range expectedKeys {
					assert.Contains(t, tmpls, key)
					tpl := tmpls[key]
					assert.NotNil(t, tpl)

					var buf bytes.Buffer
					data := map[string]string{"Value": "test"}
					assert.NoError(t, tpl.Execute(&buf, data))
					assert.Contains(t, buf.String(), "test")
				}

				assert.NotContains(t, tmpls, "ignore.txt")
				assert.NotContains(t, tmpls, filepath.Join("sub", "ignore.json"))
			},
		},
		{
			name: "ParseError",
			setup: func(t *testing.T, dir string) {
				files := map[string]string{
					"broken.yaml": "broken: {{.MissingEnd",
				}
				createTestFiles(t, dir, files)
			},
			wantErr: true,
		},
		{
			name:      "NonExistentDir",
			setup:     func(t *testing.T, dir string) {},
			dirSuffix: "non-existent",
			wantErr:   true,
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			tempDir := t.TempDir()
			if tt.setup != nil {
				tt.setup(t, tempDir)
			}

			targetDir := tempDir
			if tt.dirSuffix != "" {
				targetDir = filepath.Join(tempDir, tt.dirSuffix)
			}

			templates, err := LoadAgentConfigTemplates(targetDir)
			if tt.wantErr {
				assert.Error(t, err)
				assert.Nil(t, templates)
			} else {
				assert.NoError(t, err)
				assert.NotNil(t, templates)
				if tt.validate != nil {
					tt.validate(t, templates)
				}
			}
		})
	}
}

func createTestFiles(t *testing.T, dir string, files map[string]string) {
	for path, content := range files {
		fullPath := filepath.Join(dir, path)
		assert.NoError(t, os.MkdirAll(filepath.Dir(fullPath), 0o755))
		assert.NoError(t, os.WriteFile(fullPath, []byte(content), 0o644))
	}
}
