package install

import (
	"encoding/json"
	"os"
	"path/filepath"

	"github.com/longbin/agent-notify/internal/config"
)

const cursorHookCmd = "agent-notify hook cursor stop"
const cursorToolCmd = "agent-notify hook cursor tool"
const claudeStopCmd = "agent-notify hook claude stop"
const claudeIdleCmd = "agent-notify hook claude idle"

func CursorHooksPath() string {
	return filepath.Join(os.Getenv("HOME"), ".cursor", "hooks.json")
}

func ClaudeSettingsPath() string {
	return filepath.Join(os.Getenv("HOME"), ".claude", "settings.json")
}

func MergeCursorHooks(path string, force bool) error {
	doc := map[string]any{"version": 1, "hooks": map[string]any{}}
	if data, err := os.ReadFile(path); err == nil {
		_ = json.Unmarshal(data, &doc)
	}
	hooks, _ := doc["hooks"].(map[string]any)
	if hooks == nil {
		hooks = map[string]any{}
		doc["hooks"] = hooks
	}
	addHook(hooks, "stop", cursorHookCmd, force)
	cfg, _ := config.LoadDefault()
	if cfg.Events.Tool {
		addHook(hooks, "afterShellExecution", cursorToolCmd, force)
	}
	return writeJSON(path, doc)
}

func addHook(hooks map[string]any, name, command string, force bool) {
	if existing, ok := hooks[name]; ok && !force {
		_ = existing
		return
	}
	hooks[name] = []any{map[string]string{"command": command}}
}

func MergeClaudeSettings(path string, force bool) error {
	doc := map[string]any{}
	if data, err := os.ReadFile(path); err == nil {
		_ = json.Unmarshal(data, &doc)
	}
	hooks, _ := doc["hooks"].(map[string]any)
	if hooks == nil {
		hooks = map[string]any{}
		doc["hooks"] = hooks
	}
	setClaudeHook(hooks, "Stop", claudeStopCmd, force)
	cfg, _ := config.LoadDefault()
	if cfg.Events.Idle {
		setClaudeHook(hooks, "Notification", claudeIdleCmd, force)
	}
	return writeJSON(path, doc)
}

func setClaudeHook(hooks map[string]any, event, command string, force bool) {
	if _, ok := hooks[event]; ok && !force {
		return
	}
	hooks[event] = []any{
		map[string]any{
			"hooks": []any{
				map[string]string{
					"type":    "command",
					"command": command,
				},
			},
		},
	}
}

func writeJSON(path string, doc any) error {
	if err := os.MkdirAll(filepath.Dir(path), 0755); err != nil {
		return err
	}
	data, err := json.MarshalIndent(doc, "", "  ")
	if err != nil {
		return err
	}
	data = append(data, '\n')
	return os.WriteFile(path, data, 0644)
}

func InstallAll(force bool) error {
	if err := config.Default().WriteDefault(config.DefaultPath()); err != nil {
		return err
	}
	if err := MergeCursorHooks(CursorHooksPath(), force); err != nil {
		return err
	}
	return MergeClaudeSettings(ClaudeSettingsPath(), force)
}
