package tools

import (
	"regexp"
	"strings"
	"testing"
)

// TestExportPattern 提取 export 语句的正则表达式测试
func TestExportPattern(t *testing.T) {
	// 使用与 shell.go 相同的正则表达式
	exportPattern := regexp.MustCompile(`export\s+((?:[A-Za-z_][A-Za-z0-9_]*=\S+\s*)+)`)
	kvPattern := regexp.MustCompile(`([A-Za-z_][A-Za-z0-9_]*=\S+)`)

	tests := []struct {
		name     string
		command  string
		expected []string
	}{
		{
			name:     "单个 export",
			command:  "export PATH=/usr/local/go/bin:$PATH",
			expected: []string{"PATH=/usr/local/go/bin:$PATH"},
		},
		{
			name:     "多个 export 在同一行",
			command:  "export A=1 B=2",
			expected: []string{"A=1", "B=2"},
		},
		{
			name:     "多个 export 在不同行",
			command:  "export PATH=/a\nexport GOPATH=/root/go",
			expected: []string{"PATH=/a", "GOPATH=/root/go"},
		},
		{
			name:     "带引号的 export",
			command:  `export MY_VAR="hello"`,
			expected: []string{`MY_VAR="hello"`},
		},
		{
			name:     "没有 export 命令",
			command:  "echo hello",
			expected: nil,
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			matches := exportPattern.FindAllStringSubmatch(tt.command, -1)
			var results []string
			for _, match := range matches {
				if len(match) > 1 {
					kvMatches := kvPattern.FindAllString(match[1], -1)
					results = append(results, kvMatches...)
				}
			}

			if len(results) != len(tt.expected) {
				t.Errorf("expected %d matches, got %d: %v", len(tt.expected), len(results), results)
				return
			}

			for i, exp := range tt.expected {
				if results[i] != exp {
					t.Errorf("match %d: expected %q, got %q", i, exp, results[i])
				}
			}
		})
	}
}

func TestDetectCdTip(t *testing.T) {
	tests := []struct {
		command string
		hasTip  bool
	}{
		// Should detect
		{"cd /tmp", true},
		{"cd src && ls", true},
		{"cd src/components", true},
		{"cd ..", true},
		{"cd ~", true},
		{"ls && cd subdir", true},
		{"echo hi; cd foo", true},
		{"false || cd bar", true},

		// Should NOT detect
		{"ls -la", false},
		{"echo cd is cool", false},
		{"mkdir -p foo", false},
		{"echo 'cd /tmp'", false}, // inside string — regex is simple, may match; acceptable tradeoff
		{"abcd /tmp", false},      // "abcd" is not "cd"
		{"git checkout develop", false},
		{"grep cd file.txt", false},
	}

	for _, tt := range tests {
		tip := detectCdTip(tt.command)
		got := tip != ""
		if got != tt.hasTip {
			t.Errorf("detectCdTip(%q) = %v, want hasTip=%v", tt.command, got, tt.hasTip)
		}
	}
}

// TestEnvPersistIntegration 集成测试：模拟完整的 export 命令处理流程
func TestEnvPersistIntegration(t *testing.T) {
	exportPattern := regexp.MustCompile(`export\s+((?:[A-Za-z_][A-Za-z0-9_]*=\S+\s*)+)`)
	kvPattern := regexp.MustCompile(`([A-Za-z_][A-Za-z0-9_]*=\S+)`)

	// 模拟完整的处理流程
	processExportCommand := func(existingEnv string, command string) (string, bool) {
		if !strings.Contains(command, "export") {
			return existingEnv, false
		}

		matches := exportPattern.FindAllStringSubmatch(command, -1)
		if len(matches) == 0 {
			return existingEnv, false
		}

		var exports []string
		for _, match := range matches {
			if len(match) > 1 {
				kvMatches := kvPattern.FindAllString(match[1], -1)
				exports = append(exports, kvMatches...)
			}
		}

		if len(exports) == 0 {
			return existingEnv, false
		}

		// 合并环境变量
		envMap := make(map[string]string)
		for _, line := range strings.Split(existingEnv, "\n") {
			line = strings.TrimSpace(line)
			if line == "" || strings.HasPrefix(line, "#") {
				continue
			}
			parts := strings.SplitN(line, "=", 2)
			if len(parts) == 2 {
				envMap[parts[0]] = parts[1]
			}
		}

		for _, exp := range exports {
			parts := strings.SplitN(exp, "=", 2)
			if len(parts) == 2 {
				envMap[parts[0]] = parts[1]
			}
		}

		var lines []string
		lines = append(lines, "# Auto-generated by xbot")
		for k, v := range envMap {
			lines = append(lines, k+"="+v)
		}
		return strings.Join(lines, "\n"), true
	}

	// 测试场景：两次 export PATH
	env := ""
	env, _ = processExportCommand(env, "export PATH=/usr/local/go/bin:$PATH")
	if !strings.Contains(env, "PATH=/usr/local/go/bin:$PATH") {
		t.Errorf("first export failed: %s", env)
	}

	// 再次 export PATH
	env, _ = processExportCommand(env, "export PATH=/new/path")
	if !strings.Contains(env, "PATH=/new/path") {
		t.Errorf("second export failed: %s", env)
	}
	if strings.Contains(env, "/usr/local/go/bin") {
		t.Errorf("old PATH should be replaced, got: %s", env)
	}

	// 检查只有一行 PATH
	pathCount := strings.Count(env, "PATH=")
	if pathCount != 1 {
		t.Errorf("expected 1 PATH entry, got %d: %s", pathCount, env)
	}
}
