package main

import (
	"bufio"
	"fmt"
	"os"
	"strings"
)

// applyStandardModifications handles `standard` type patches
func applyStandardModifications(targetFilePath string, modifications []string) error {
	fmt.Printf("Applying standard modifications to file: %s\n", targetFilePath)

	// Open the target file for reading and writing
	file, err := os.OpenFile(targetFilePath, os.O_RDWR, 0644)
	if err != nil {
		return fmt.Errorf("failed to open target file '%s': %v", targetFilePath, err)
	}
	defer file.Close()

	scanner := bufio.NewScanner(file)
	targetLines := []string{}

	// Read all lines from the target file
	for scanner.Scan() {
		targetLines = append(targetLines, scanner.Text())
	}
	if err := scanner.Err(); err != nil {
		return fmt.Errorf("failed to read target file '%s': %v", targetFilePath, err)
	}

	modifiedLines := map[string]bool{}
	modMap := parseModifications(modifications)

	var updatedContent strings.Builder

	// Apply modifications to the target lines
	for _, line := range targetLines {
		lineModified := false

		for key, mod := range modMap {
			if strings.Contains(line, key) && !modifiedLines[key] {
				fmt.Printf("Replacing line in file '%s': %s -> %s\n", targetFilePath, line, mod)
				updatedContent.WriteString(mod + "\n")
				modifiedLines[key] = true
				lineModified = true
				break
			}
		}

		// Write the original line if no modification matches
		if !lineModified {
			updatedContent.WriteString(line + "\n")
		}
	}

	// Append any remaining modifications that were not applied
	for key, mod := range modMap {
		if !modifiedLines[key] {
			fmt.Printf("Adding new line to file '%s': %s\n", targetFilePath, mod)
			updatedContent.WriteString(mod + "\n")
		}
	}

	// Truncate and rewrite the file with updated content
	if err := file.Truncate(0); err != nil {
		return fmt.Errorf("failed to truncate file '%s': %v", targetFilePath, err)
	}
	if _, err := file.Seek(0, 0); err != nil {
		return fmt.Errorf("failed to reset file pointer for '%s': %v", targetFilePath, err)
	}
	if _, err := file.WriteString(updatedContent.String()); err != nil {
		return fmt.Errorf("failed to write updated content to file '%s': %v", targetFilePath, err)
	}

	fmt.Printf("Standard modifications successfully applied to file: %s\n", targetFilePath)
	return nil
}

// parseModifications converts a list of modification strings into a map for processing
func parseModifications(modifications []string) map[string]string {
	modMap := map[string]string{}
	for _, mod := range modifications {
		if strings.HasPrefix(mod, "+") || strings.HasPrefix(mod, "-") {
			trimmed := strings.TrimSpace(strings.TrimPrefix(mod, "+"))
			trimmed = strings.TrimPrefix(trimmed, "-")
			key := extractKey(trimmed)
			modMap[key] = trimmed
		}
	}
	return modMap
}

// extractKey extracts the key from a modification string
func extractKey(line string) string {
	start := strings.Index(line, "(")
	end := strings.LastIndex(line, ")")
	if start > 0 && end > start {
		return strings.TrimSpace(line[start+1 : end])
	}
	return line // Fallback: return the full line
}
