package cmd

import (
	"bytes"
	"fmt"
	"os"
	"os/exec"
	"strings"

	"github.com/cupcakearmy/autorestic/internal"
	"github.com/cupcakearmy/autorestic/internal/colors"
	"github.com/cupcakearmy/autorestic/internal/lock"
	"github.com/spf13/cobra"
)

var unlockCmd = &cobra.Command{
	Use:   "unlock",
	Short: "Unlock autorestic only if you are sure that no other instance is running",
	Long: `Unlock autorestic only if you are sure that no other instance is running.
To check you can run "ps aux | grep autorestic".`,
	Run: func(cmd *cobra.Command, args []string) {
		internal.GetConfig()

		force, _ := cmd.Flags().GetBool("force")

		if !force && isAutoresticRunning() {
			colors.Error.Print("Another autorestic instance is running. Are you sure you want to unlock? (yes/no): ")
			var response string
			fmt.Scanln(&response)
			if strings.ToLower(response) != "yes" {
				colors.Primary.Println("Unlocking aborted.")
				return
			}
		}

		err := lock.Unlock()
		if err != nil {
			colors.Error.Println("Could not unlock:", err)
			return
		}

		colors.Success.Println("Unlock successful")
	},
}

func init() {
	rootCmd.AddCommand(unlockCmd)
	unlockCmd.Flags().Bool("force", false, "force unlock")
}

// isAutoresticRunning checks if autorestic is running
// and returns true if it is.
// It also prints the processes to stdout.
func isAutoresticRunning() bool {
	cmd := exec.Command("sh", "-c", "ps aux | grep autorestic")
	var out bytes.Buffer
	cmd.Stdout = &out
	err := cmd.Run()
	if err != nil {
		return false
	}

	lines := strings.Split(out.String(), "\n")
	autoresticProcesses := []string{}
	currentPid := fmt.Sprint(os.Getpid())

	for _, line := range lines {
		if strings.Contains(line, "autorestic") && !strings.Contains(line, "grep autorestic") && !strings.Contains(line, currentPid) {
			autoresticProcesses = append(autoresticProcesses, line)
		}
	}

	if len(autoresticProcesses) > 0 {
		colors.Faint.Println("Found autorestic processes:")
		for _, proc := range autoresticProcesses {
			colors.Faint.Println(proc)
		}
		return true
	}
	return false
}