// Package main provides the post-tool-use hook entry point.
package main

import (
	"context"
	"fmt"
	"os"
	"time"

	"github.com/lukaszraczylo/claude-mnemonic/pkg/hooks"
)

// Input is the hook input from Claude Code.
type Input struct {
	hooks.BaseInput
	ToolName     string      `json:"tool_name"`
	ToolInput    interface{} `json:"tool_input"`
	ToolResponse interface{} `json:"tool_response"`
	ToolUseID    string      `json:"tool_use_id"`
}

// skipTools lists tools that never produce useful observations.
// Skip the HTTP call entirely for these to reduce overhead during heavy tool usage.
var skipTools = map[string]bool{
	// Internal tracking tools (but NOT TodoWrite - it captures planned work)
	"Task":       true,
	"TaskOutput": true,

	// File discovery tools (just listings, no insights)
	"Glob":      true,
	"ListDir":   true,
	"LS":        true,
	"KillShell": true,

	// Question/interaction tools (no code insights)
	"AskUserQuestion": true,

	// Plan mode tools (planning, not execution)
	"EnterPlanMode": true,
	"ExitPlanMode":  true,

	// Skill/command execution (meta-operations)
	"Skill":        true,
	"SlashCommand": true,

	// Read is high-volume and rarely produces insights worth the overhead
	// The processor would skip most reads anyway after filtering
	"Read": true,

	// Search tools are for finding, not modifying
	"Grep":      true,
	"WebSearch": true,
}

func main() {
	if !hooks.IsWorkerAvailable() {
		hooks.WriteResponse("PostToolUse", true)
		return
	}
	hooks.RunHook("PostToolUse", handlePostToolUse)
}

func handlePostToolUse(ctx *hooks.HookContext, input *Input) (string, error) {
	// Skip HTTP call entirely for tools that never produce useful observations.
	// This significantly reduces overhead during heavy tool usage.
	if skipTools[input.ToolName] {
		return "", nil
	}

	fmt.Fprintf(os.Stderr, "[post-tool-use] %s\n", input.ToolName)

	// Fire-and-forget: send the observation without waiting for the response.
	// The worker just queues it -- we don't need the response data.
	// Use a short-lived context to ensure the request body is at least sent
	// before this process exits.
	done := make(chan struct{})
	go func() {
		defer close(done)
		sendCtx, cancel := context.WithTimeout(context.Background(), 500*time.Millisecond)
		defer cancel()
		_ = hooks.POSTWithContext(sendCtx, ctx.Port, "/api/sessions/observations", map[string]interface{}{
			"claudeSessionId": ctx.SessionID,
			"project":         ctx.Project,
			"tool_name":       input.ToolName,
			"tool_input":      input.ToolInput,
			"tool_response":   input.ToolResponse,
			"cwd":             ctx.CWD,
		})
	}()

	// Wait briefly for the TCP connection to be established and request sent,
	// but don't block the hook for the full response.
	select {
	case <-done:
	case <-time.After(100 * time.Millisecond):
	}

	return "", nil
}
