package main
import (
	"os"
	"regexp"
	"strings"
	"testing"
)
// Helper function to normalize whitespace for comparison
func normalizeWhitespace(s string) string {
	// Replace all whitespace with a single space
	re := regexp.MustCompile(`\s+`)
	return re.ReplaceAllString(strings.TrimSpace(s), " ")
}
func TestSimpleValueMultiplication(t *testing.T) {
	fileContents := `
		
			- 
				100
			
 
		
	`
	expected := `
		
			- 
				150
			
 
		
	`
	// Create a regex pattern with the (?s) flag for multiline matching
	regex := regexp.MustCompile(`(?s)(\d+)`)
	luaExpr := `*1.5`
	luaScript := buildLuaScript(luaExpr)
	modifiedContent, err := process(fileContents, regex, luaScript)
	if err != nil {
		t.Fatalf("Error processing file: %v", err)
	}
	// Compare normalized content
	normalizedModified := normalizeWhitespace(modifiedContent)
	normalizedExpected := normalizeWhitespace(expected)
	if normalizedModified != normalizedExpected {
		t.Fatalf("Expected modified content to be %q, but got %q", normalizedExpected, normalizedModified)
	}
}
func TestShorthandNotation(t *testing.T) {
	fileContents := `
		
			- 
				100
			
 
		
	`
	expected := `
		
			- 
				150
			
 
		
	`
	regex := regexp.MustCompile(`(?s)(\d+)`)
	luaExpr := `v1 * 1.5`
	luaScript := buildLuaScript(luaExpr)
	modifiedContent, err := process(fileContents, regex, luaScript)
	if err != nil {
		t.Fatalf("Error processing file: %v", err)
	}
	normalizedModified := normalizeWhitespace(modifiedContent)
	normalizedExpected := normalizeWhitespace(expected)
	if normalizedModified != normalizedExpected {
		t.Fatalf("Expected modified content to be %q, but got %q", normalizedExpected, normalizedModified)
	}
}
func TestArrayNotation(t *testing.T) {
	fileContents := `
		
			- 
				100
			
 
		
	`
	expected := `
		
			- 
				150
			
 
		
	`
	regex := regexp.MustCompile(`(?s)(\d+)`)
	luaExpr := `v1 * 1.5`
	luaScript := buildLuaScript(luaExpr)
	modifiedContent, err := process(fileContents, regex, luaScript)
	if err != nil {
		t.Fatalf("Error processing file: %v", err)
	}
	normalizedModified := normalizeWhitespace(modifiedContent)
	normalizedExpected := normalizeWhitespace(expected)
	if normalizedModified != normalizedExpected {
		t.Fatalf("Expected modified content to be %q, but got %q", normalizedExpected, normalizedModified)
	}
}
func TestMultipleMatches(t *testing.T) {
	fileContents := `
		
			- 
				100
			
 
			- 
				200
			
 
			-  300 
 
		
	`
	expected := `
		
			- 
				150
			
 
			- 
				300
			
 
			-  450 
 
		
	`
	regex := regexp.MustCompile(`(?s)(\d+)`)
	luaExpr := `*1.5`
	luaScript := buildLuaScript(luaExpr)
	modifiedContent, err := process(fileContents, regex, luaScript)
	if err != nil {
		t.Fatalf("Error processing file: %v", err)
	}
	normalizedModified := normalizeWhitespace(modifiedContent)
	normalizedExpected := normalizeWhitespace(expected)
	if normalizedModified != normalizedExpected {
		t.Fatalf("Expected modified content to be %q, but got %q", normalizedExpected, normalizedModified)
	}
}
func TestMultipleCaptureGroups(t *testing.T) {
	fileContents := `
		
			- 
				10
				5
			
 
		
	`
	expected := `
		
			- 
				50
				5
			
 
		
	`
	// Use (?s) flag to match across multiple lines
	regex := regexp.MustCompile(`(?s)(\d+).*?(\d+)`)
	luaExpr := `v1 * v2`
	luaScript := buildLuaScript(luaExpr)
	// Verify the regex matches before processing
	matches := regex.FindStringSubmatch(fileContents)
	if len(matches) <= 1 {
		t.Fatalf("Regex didn't match any capture groups in test input: %v", fileContents)
	}
	t.Logf("Matches: %v", matches)
	modifiedContent, err := process(fileContents, regex, luaScript)
	if err != nil {
		t.Fatalf("Error processing file: %v", err)
	}
	normalizedModified := normalizeWhitespace(modifiedContent)
	normalizedExpected := normalizeWhitespace(expected)
	if normalizedModified != normalizedExpected {
		t.Fatalf("Expected modified content to be %q, but got %q", normalizedExpected, normalizedModified)
	}
}
func TestModifyingMultipleValues(t *testing.T) {
	fileContents := `
		
			- 
				50
				3
				2
			
 
		
	`
	expected := `
		
			- 
				75
				5
				1
			
 
		
	`
	regex := regexp.MustCompile(`(?s)(\d+).*?(\d+).*?(\d+)`)
	luaExpr := `v1 = v1 * v2 / v3; v2 = min(v2 * 2, 5); v3 = max(1, v3 / 2)`
	luaScript := buildLuaScript(luaExpr)
	// Verify the regex matches before processing
	matches := regex.FindStringSubmatch(fileContents)
	if len(matches) <= 1 {
		t.Fatalf("Regex didn't match any capture groups in test input: %v", fileContents)
	}
	t.Logf("Matches: %v", matches)
	modifiedContent, err := process(fileContents, regex, luaScript)
	if err != nil {
		t.Fatalf("Error processing file: %v", err)
	}
	normalizedModified := normalizeWhitespace(modifiedContent)
	normalizedExpected := normalizeWhitespace(expected)
	if normalizedModified != normalizedExpected {
		t.Fatalf("Expected modified content to be %q, but got %q", normalizedExpected, normalizedModified)
	}
}
func TestDecimalValues(t *testing.T) {
	fileContents := `
		
			- 
				10.5
				2.5
			
 
		
	`
	expected := `
		
			- 
				26.25
				2.5
			
 
		
	`
	regex := regexp.MustCompile(`(?s)([0-9.]+).*?([0-9.]+)`)
	luaExpr := `v1 * v2`
	luaScript := buildLuaScript(luaExpr)
	modifiedContent, err := process(fileContents, regex, luaScript)
	if err != nil {
		t.Fatalf("Error processing file: %v", err)
	}
	normalizedModified := normalizeWhitespace(modifiedContent)
	normalizedExpected := normalizeWhitespace(expected)
	if normalizedModified != normalizedExpected {
		t.Fatalf("Expected modified content to be %q, but got %q", normalizedExpected, normalizedModified)
	}
}
func TestLuaMathFunctions(t *testing.T) {
	fileContents := `
		
			- 
				16
			
 
		
	`
	expected := `
		
			- 
				4
			
 
		
	`
	regex := regexp.MustCompile(`(?s)(\d+)`)
	luaExpr := `math.sqrt(v1)`
	luaScript := buildLuaScript(luaExpr)
	modifiedContent, err := process(fileContents, regex, luaScript)
	if err != nil {
		t.Fatalf("Error processing file: %v", err)
	}
	normalizedModified := normalizeWhitespace(modifiedContent)
	normalizedExpected := normalizeWhitespace(expected)
	if normalizedModified != normalizedExpected {
		t.Fatalf("Expected modified content to be %q, but got %q", normalizedExpected, normalizedModified)
	}
}
func TestDirectAssignment(t *testing.T) {
	fileContents := `
		
			- 
				100
			
 
		
	`
	expected := `
		
			- 
				0
			
 
		
	`
	regex := regexp.MustCompile(`(?s)(\d+)`)
	luaExpr := `=0`
	luaScript := buildLuaScript(luaExpr)
	t.Logf("Lua script: %s", luaScript) // Log the generated script for debugging
	modifiedContent, err := process(fileContents, regex, luaScript)
	if err != nil {
		t.Fatalf("Error processing file: %v", err)
	}
	normalizedModified := normalizeWhitespace(modifiedContent)
	normalizedExpected := normalizeWhitespace(expected)
	if normalizedModified != normalizedExpected {
		t.Fatalf("Expected modified content to be %q, but got %q", normalizedExpected, normalizedModified)
	}
}
// Test with actual files
func TestProcessingSampleFiles(t *testing.T) {
	// Read test files
	complexFile, err := os.ReadFile("test_complex.xml")
	if err != nil {
		t.Fatalf("Error reading test_complex.xml: %v", err)
	}
	testDataFile, err := os.ReadFile("test_data.xml")
	if err != nil {
		t.Fatalf("Error reading test_data.xml: %v", err)
	}
	testCases := []struct {
		name         string
		fileContent  string
		regexPattern string
		luaExpr      string
		expectedFunc func(string) string // Function to generate expected output
	}{
		{
			name:         "Complex file - multiply values by multiplier and divide by divider",
			fileContent:  string(complexFile),
			regexPattern: `(?s)(\d+).*?(\d+).*?(\d+)`,
			luaExpr:      `v1 * v2 / v3`,
			expectedFunc: func(content string) string {
				// Replace values manually for verification
				r := regexp.MustCompile(`(?s)- \s*150\s*2\s*4\s*
 `)
				content = r.ReplaceAllString(content, "- \n    75\n    2\n    4\n  
 ")
				r = regexp.MustCompile(`(?s)- \s*300\s*3\s*2\s*
 `)
				content = r.ReplaceAllString(content, "- \n    450\n    3\n    2\n  
 ")
				return content
			},
		},
		{
			name:         "Test data - simple multiplication",
			fileContent:  string(testDataFile),
			regexPattern: `(?s).*?(\d+).*?`,
			luaExpr:      `*1.5`,
			expectedFunc: func(content string) string {
				r := regexp.MustCompile(`100`)
				return r.ReplaceAllString(content, "150")
			},
		},
		{
			name:         "Test data - multiple capture groups",
			fileContent:  string(testDataFile),
			regexPattern: `(?s).*?(\d+).*?(\d+).*?(\d+).*?`,
			luaExpr:      `v1 * v2 / v3`,
			expectedFunc: func(content string) string {
				r := regexp.MustCompile(`50`)
				return r.ReplaceAllString(content, "75")
			},
		},
		{
			name:         "Test data - decimal values",
			fileContent:  string(testDataFile),
			regexPattern: `(?s).*?([0-9.]+).*?([0-9.]+).*?`,
			luaExpr:      `v1 * v2`,
			expectedFunc: func(content string) string {
				r := regexp.MustCompile(`10.5`)
				return r.ReplaceAllString(content, "26.25")
			},
		},
	}
	for _, tc := range testCases {
		t.Run(tc.name, func(t *testing.T) {
			regex := regexp.MustCompile(tc.regexPattern)
			luaScript := buildLuaScript(tc.luaExpr)
			// Debug information
			t.Logf("Regex pattern: %s", tc.regexPattern)
			t.Logf("Lua expression: %s", tc.luaExpr)
			// Process the content
			modifiedContent, err := process(tc.fileContent, regex, luaScript)
			if err != nil {
				t.Fatalf("Error processing file: %v", err)
			}
			t.Logf("Modified content has length: %d", len(modifiedContent))
			// Generate expected content
			expectedContent := tc.expectedFunc(tc.fileContent)
			t.Logf("Expected content has length: %d", len(expectedContent))
			// Compare normalized content
			normalizedModified := normalizeWhitespace(modifiedContent)
			normalizedExpected := normalizeWhitespace(expectedContent)
			// Check if the specific section was modified as expected
			if !strings.Contains(normalizedModified, normalizeWhitespace(expectedContent)) {
				t.Logf("Modified content: %s", normalizedModified)
				t.Logf("Expected content: %s", normalizedExpected)
				t.Fatalf("Expected modification not found in result")
			} else {
				t.Logf("Test passed - expected modification found in result")
			}
		})
	}
}
func TestFileOperations(t *testing.T) {
	// Test file operations with sample XML files
	// Test 1: Complex file with multiple items
	t.Run("Complex file operations", func(t *testing.T) {
		// Read test file
		complexFile, err := os.ReadFile("test_complex.xml")
		if err != nil {
			t.Fatalf("Error reading test_complex.xml: %v", err)
		}
		fileContent := string(complexFile)
		// Configure test
		regexPattern := `(?s)(\d+).*?(\d+).*?(\d+)`
		luaExpr := `v1 * v2 / v3`
		// Execute test
		regex := regexp.MustCompile(regexPattern)
		luaScript := buildLuaScript(luaExpr)
		t.Logf("Regex pattern: %s", regexPattern)
		t.Logf("Lua expression: %s", luaExpr)
		// Process the content
		modifiedContent, err := process(fileContent, regex, luaScript)
		if err != nil {
			t.Fatalf("Error processing file: %v", err)
		}
		// Verify results - should have 75 and 450 as values
		t.Logf("Modified content: %s", modifiedContent)
		if !strings.Contains(modifiedContent, "75") {
			t.Errorf("First value not modified correctly, expected 75")
		}
		if !strings.Contains(modifiedContent, "450") {
			t.Errorf("Second value not modified correctly, expected 450")
		}
		t.Logf("Complex file test completed successfully")
	})
	// Test 2: Test data file with simple multiplication
	t.Run("Simple multiplication in test data", func(t *testing.T) {
		// Read test file
		testDataFile, err := os.ReadFile("test_data.xml")
		if err != nil {
			t.Fatalf("Error reading test_data.xml: %v", err)
		}
		fileContent := string(testDataFile)
		// Configure test for simple value
		regexPattern := `(?s).*?(\d+).*?`
		luaExpr := `*1.5`
		// Execute test
		regex := regexp.MustCompile(regexPattern)
		luaScript := buildLuaScript(luaExpr)
		t.Logf("Regex pattern: %s", regexPattern)
		t.Logf("Lua expression: %s", luaExpr)
		// Process the content
		modifiedContent, err := process(fileContent, regex, luaScript)
		if err != nil {
			t.Fatalf("Error processing file: %v", err)
		}
		// Check for expected value (100 * 1.5 = 150)
		if !strings.Contains(modifiedContent, "150") {
			t.Errorf("Value not modified correctly, expected 150 in the simple test")
			t.Logf("Modified content: %s", modifiedContent)
		} else {
			t.Logf("Simple test passed - found 150")
		}
	})
	// Test 3: Decimal values
	t.Run("Decimal values in test data", func(t *testing.T) {
		// Read test file
		testDataFile, err := os.ReadFile("test_data.xml")
		if err != nil {
			t.Fatalf("Error reading test_data.xml: %v", err)
		}
		fileContent := string(testDataFile)
		// Configure test for decimal values
		regexPattern := `(?s).*?([0-9.]+).*?([0-9.]+).*?`
		luaExpr := `v1 * v2`
		// Execute test
		regex := regexp.MustCompile(regexPattern)
		luaScript := buildLuaScript(luaExpr)
		t.Logf("Regex pattern: %s", regexPattern)
		t.Logf("Lua expression: %s", luaExpr)
		// Process the content
		modifiedContent, err := process(fileContent, regex, luaScript)
		if err != nil {
			t.Fatalf("Error processing file: %v", err)
		}
		// Check for expected value (10.5 * 2.5 = 26.25)
		if !strings.Contains(modifiedContent, "26.25") {
			t.Errorf("Decimal value not modified correctly, expected 26.25")
			t.Logf("Modified content: %s", modifiedContent)
		} else {
			t.Logf("Decimal test passed - found 26.25")
		}
	})
}
func TestHigherVariableIndices(t *testing.T) {
	fileContents := `
		
			- 
				10
				20
				30
				40
				50
				110
			
 
		
	`
	// Test using v3, v4, v5 in the expression
	t.Run("Using v3-v5 variables", func(t *testing.T) {
		regex := regexp.MustCompile(`(?s)(\d+).*?(\d+).*?(\d+).*?(\d+).*?(\d+)`)
		luaExpr := `v1 + v2 * v3 / v4 - v5`
		luaScript := buildLuaScript(luaExpr)
		// Expected: 10 + 20 * 30 / 40 - 50 = 10 + 15 - 50 = -25
		modifiedContent, err := process(fileContents, regex, luaScript)
		if err != nil {
			t.Fatalf("Error processing with v3-v5: %v", err)
		}
		// The result should replace the first value
		if !strings.Contains(modifiedContent, "-25") {
			t.Fatalf("Failed to process v3-v5 correctly. Expected -25, got: %s", modifiedContent)
		}
	})
	// Test using v11 (double digit index)
	// For double digit indexes, we need to capture it as the second variable (v2)
	t.Run("Using v11 variable", func(t *testing.T) {
		regex := regexp.MustCompile(`(?s)(\d+).*?(\d+)`)
		luaExpr := `v1 * v2`
		luaScript := buildLuaScript(luaExpr)
		// Expected: 10 * 110 = 1100
		modifiedContent, err := process(fileContents, regex, luaScript)
		if err != nil {
			t.Fatalf("Error processing with v11: %v", err)
		}
		// The result should replace the first value
		if !strings.Contains(modifiedContent, "1100") {
			t.Fatalf("Failed to process v11 correctly. Expected 1100, got: %s", modifiedContent)
		}
	})
	// Test using v0 (zero index)
	t.Run("Using v0 variable", func(t *testing.T) {
		// For this test, we'll capture the tag content and manipulate it
		regex := regexp.MustCompile(`(?s)(\d+)`)
		luaExpr := `tonumber(v1) * 2`
		luaScript := buildLuaScript(luaExpr)
		// This should double the value
		modifiedContent, err := process(fileContents, regex, luaScript)
		if err != nil {
			t.Fatalf("Error processing with v0: %v", err)
		}
		// Should replace 10 with 20
		if !strings.Contains(modifiedContent, "20") {
			t.Fatalf("Failed to process test correctly. Expected 20, got: %s", modifiedContent)
		}
	})
}