package cmd

import (
	_ "embed"
	"fmt"
	"os"
	"path/filepath"
	"strings"
	"time"

	"github.com/spf13/cobra"
)

//go:embed hook_script.sh
var hookScript string

// hookMarker identifies a KeyHunter-managed hook. Uninstall refuses to
// delete pre-commit files that don't contain this marker unless --force.
const hookMarker = "KEYHUNTER-HOOK v1"

var (
	hookForce bool
)

var hookCmd = &cobra.Command{
	Use:   "hook",
	Short: "Install or manage git pre-commit hooks",
}

var hookInstallCmd = &cobra.Command{
	Use:   "install",
	Short: "Install the keyhunter pre-commit hook into .git/hooks/",
	RunE:  runHookInstall,
}

var hookUninstallCmd = &cobra.Command{
	Use:   "uninstall",
	Short: "Remove the keyhunter pre-commit hook",
	RunE:  runHookUninstall,
}

func init() {
	hookInstallCmd.Flags().BoolVar(&hookForce, "force", false, "overwrite any existing pre-commit hook without prompt")
	hookUninstallCmd.Flags().BoolVar(&hookForce, "force", false, "delete pre-commit even if it is not KeyHunter-managed")
	hookCmd.AddCommand(hookInstallCmd)
	hookCmd.AddCommand(hookUninstallCmd)
}

func hookPath() (string, error) {
	gitDir := ".git"
	info, err := os.Stat(gitDir)
	if err != nil || !info.IsDir() {
		return "", fmt.Errorf("not a git repository (no .git/ in current directory)")
	}
	return filepath.Join(gitDir, "hooks", "pre-commit"), nil
}

func runHookInstall(cmd *cobra.Command, args []string) error {
	target, err := hookPath()
	if err != nil {
		return err
	}
	if _, err := os.Stat(target); err == nil {
		existing, _ := os.ReadFile(target)
		if strings.Contains(string(existing), hookMarker) {
			// Already ours — overwrite silently to update script.
		} else if !hookForce {
			return fmt.Errorf("pre-commit hook already exists at %s (use --force to overwrite; a .bak backup will be kept)", target)
		} else {
			backup := target + ".bak." + time.Now().Format("20060102150405")
			if err := os.Rename(target, backup); err != nil {
				return fmt.Errorf("backing up existing hook: %w", err)
			}
			fmt.Fprintf(cmd.OutOrStdout(), "Backed up existing hook to %s\n", backup)
		}
	}
	if err := os.MkdirAll(filepath.Dir(target), 0o755); err != nil {
		return fmt.Errorf("creating hooks dir: %w", err)
	}
	if err := os.WriteFile(target, []byte(hookScript), 0o755); err != nil {
		return fmt.Errorf("writing hook: %w", err)
	}
	fmt.Fprintf(cmd.OutOrStdout(), "Installed pre-commit hook at %s\n", target)
	return nil
}

func runHookUninstall(cmd *cobra.Command, args []string) error {
	target, err := hookPath()
	if err != nil {
		return err
	}
	data, err := os.ReadFile(target)
	if err != nil {
		if os.IsNotExist(err) {
			fmt.Fprintln(cmd.OutOrStdout(), "No pre-commit hook to remove.")
			return nil
		}
		return fmt.Errorf("reading hook: %w", err)
	}
	if !strings.Contains(string(data), hookMarker) && !hookForce {
		return fmt.Errorf("pre-commit at %s is not KeyHunter-managed (use --force to remove anyway)", target)
	}
	if err := os.Remove(target); err != nil {
		return fmt.Errorf("removing hook: %w", err)
	}
	fmt.Fprintf(cmd.OutOrStdout(), "Removed pre-commit hook at %s\n", target)
	return nil
}
