package main

import (
	"fmt"
	"regexp"
	"strings"
)

var exitCodeMarkerRe = regexp.MustCompile(`^\[(\d+|\*)\]$`)

func rewriteFile(file ShoutFile, results []CommandResult, originalContent string) string {
	lines := strings.Split(originalContent, "\n")
	var output []string

	cmdIdx := 0

	for i := 0; i < len(lines); i++ {
		line := lines[i]

		if strings.HasPrefix(line, "$ ") {
			output = append(output, line)

			if cmdIdx >= len(file.Commands) || cmdIdx >= len(results) {
				// Out of bounds — skip past expected output, preserving original lines
				j := i + 1
				for j < len(lines) && !strings.HasPrefix(lines[j], "$ ") {
					j++
				}
				output = append(output, lines[i+1:j]...)
				i = j - 1
				cmdIdx++
				continue
			}

			cmd := file.Commands[cmdIdx]
			result := results[cmdIdx]

			// Skip past old expected output lines
			j := i + 1
			for j < len(lines) && !strings.HasPrefix(lines[j], "$ ") {
				j++
			}

			oldExpectedRaw := lines[i+1 : j]

			// Count trailing blank lines
			trailingBlanks := 0
			for k := len(oldExpectedRaw) - 1; k >= 0; k-- {
				if oldExpectedRaw[k] == "" {
					trailingBlanks++
				} else {
					break
				}
			}

			// If wildcards match, keep original
			if matchOutput(cmd.Expected, result.Actual) {
				output = append(output, oldExpectedRaw...)
			} else {
				output = append(output, result.Actual...)
				if result.ExitCode != 0 {
					output = append(output, fmt.Sprintf("[%d]", result.ExitCode))
				} else if len(result.Actual) > 0 && exitCodeMarkerRe.MatchString(result.Actual[len(result.Actual)-1]) {
					// Actual output's last line looks like an exit code marker.
					// Add an explicit [0] to prevent parser from consuming it.
					output = append(output, "[0]")
				}
				for k := 0; k < trailingBlanks; k++ {
					output = append(output, "")
				}
			}

			i = j - 1
			cmdIdx++
		} else if cmdIdx == 0 || cmdIdx >= len(file.Commands) {
			output = append(output, line)
		}
	}

	return strings.Join(output, "\n")
}
