package spitfire

import (
	"fmt"
	"os"
	"os/exec"
	"path/filepath"
)

// ApplyPatches handles cloning, updating, and applying patches
func ApplyPatches(sourcePath string, patchesRepo string, patchesPath string, patchesCloneDir string, skipUpdateRepo bool) error {
	// Define the full patches path
	fullPatchesPath := filepath.Join(patchesCloneDir, patchesPath) // Cleaned path without double slashes

	fmt.Printf("Source Path: %s\n", sourcePath)
	fmt.Printf("Patches Clone Directory: %s\n", patchesCloneDir)
	fmt.Printf("Patches Repository URL: %s\n", patchesRepo)
	fmt.Printf("Patches Path: %s\n", fullPatchesPath)

	// Check if the patches directory already exists
	if _, err := os.Stat(patchesCloneDir); os.IsNotExist(err) {
		// Clone the patches repository
		fmt.Println("Patches directory does not exist. Proceeding to clone.")
		cmdClone := exec.Command("git", "clone", patchesRepo, patchesCloneDir)
		cmdClone.Stdout = os.Stdout
		cmdClone.Stderr = os.Stderr
		if err := cmdClone.Run(); err != nil {
			return fmt.Errorf("failed to clone patches repository: %v", err)
		}
		fmt.Println("Patches repository cloned successfully.")
	} else {
		if !skipUpdateRepo {
			// If the directory exists, fetch and pull the latest changes
			fmt.Println("Patches directory already exists. Fetching latest changes.")
			cmdFetch := exec.Command("git", "fetch", "--all")
			cmdFetch.Dir = patchesCloneDir
			cmdFetch.Stdout = os.Stdout
			cmdFetch.Stderr = os.Stderr
			if err := cmdFetch.Run(); err != nil {
				return fmt.Errorf("failed to fetch updates for patches repository: %v", err)
			}

			cmdReset := exec.Command("git", "reset", "--hard", "origin/main")
			cmdReset.Dir = patchesCloneDir
			cmdReset.Stdout = os.Stdout
			cmdReset.Stderr = os.Stderr
			if err := cmdReset.Run(); err != nil {
				return fmt.Errorf("failed to reset patches repository to latest state: %v", err)
			}
			fmt.Println("Patches repository updated successfully.")
		}
	}

	// Verify the patches directory exists
	if _, err := os.Stat(fullPatchesPath); os.IsNotExist(err) {
		return fmt.Errorf("patches path not found: %s", fullPatchesPath)
	}

	// Apply the patches using `run.sh`
	applyCmd := exec.Command("go", "run", ".", "--path", sourcePath, "--patches", fullPatchesPath)
	applyCmd.Dir = patchesCloneDir // Run from the patches directory
	applyCmd.Stdout = os.Stdout
	applyCmd.Stderr = os.Stderr
	fmt.Println("Applying patches...")
	if err := applyCmd.Run(); err != nil {
		return fmt.Errorf("failed to apply patches: %v", err)
	}

	fmt.Println("Patches applied successfully.")
	return nil
}