#!/usr/bin/env python3
# @CODE:HOOKS-REFACTOR-001 | SPEC: SPEC-HOOKS-REFACTOR-001.md
"""Alfred Hooks - Main entry point for MoAI-ADK Claude Code Hooks

A main entry point that routes Claude Code events to the appropriate handlers.

🏗️ Architecture:
┌─────────────────────────────────────────────────────────────┐
│ alfred_hooks.py (Router)                                    │
├─────────────────────────────────────────────────────────────┤
│ - CLI argument parsing                                      │
│ - JSON I/O (stdin/stdout)                                   │
│ - Event routing to handlers                                 │
└─────────────────────────────────────────────────────────────┘
                         ▼
┌─────────────────────────────────────────────────────────────┐
│ handlers/ (Event Handlers)                                  │
├─────────────────────────────────────────────────────────────┤
│ - session.py: SessionStart, SessionEnd                      │
│ - user.py: UserPromptSubmit                                 │
│ - tool.py: PreToolUse, PostToolUse                          │
│ - notification.py: Notification, Stop, SubagentStop         │
└─────────────────────────────────────────────────────────────┘
                         ▼
┌─────────────────────────────────────────────────────────────┐
│ core/ (Business Logic)                                      │
├─────────────────────────────────────────────────────────────┤
│ - project.py: Language detection, Git info, SPEC progress   │
│ - context.py: JIT Retrieval, workflow context               │
│ - checkpoint.py: Event-Driven Checkpoint system             │
│ - tags.py: TAG search/verification, library version cache   │
└─────────────────────────────────────────────────────────────┘

🛠️ Usage:
    python alfred_hooks.py <event_name> < payload.json

📣 Supported Events:
    - SessionStart: Start Session (display project status)
    - UserPromptSubmit: Prompt submission (JIT document loading)
    - PreToolUse: Before using the tool (automatically creates checkpoint)
    - SessionEnd, PostToolUse, Notification, Stop, SubagentStop

🚦 Exit Codes:
    - 0: Success
    - 1: Error (no arguments, JSON parsing failure, exception thrown)

🧪 TDD History:
    - RED: Module separation design, event routing test
    - GREEN: 1233 LOC → 9 items Module separation implementation (SRP compliance)
    - REFACTOR: Import optimization, enhanced error handling

Setup sys.path for package imports
"""

import json
import signal
import sys
from pathlib import Path
from typing import Any

# Add the hooks directory to sys.path BEFORE any imports (critical!)
HOOKS_DIR = Path(__file__).parent
SHARED_DIR = HOOKS_DIR / "shared"
if str(SHARED_DIR) not in sys.path:
    sys.path.insert(0, str(SHARED_DIR))
if str(HOOKS_DIR) not in sys.path:
    sys.path.insert(0, str(HOOKS_DIR))

from handlers import (
    handle_notification,
    handle_post_tool_use,
    handle_pre_tool_use,
    handle_session_end,
    handle_session_start,
    handle_stop,
    handle_subagent_stop,
    handle_user_prompt_submit,
)
from shared.core import HookResult
from utils.timeout import TimeoutError as PlatformTimeoutError


def _hook_timeout_handler(signum, frame):
    """Signal handler for global hook timeout"""
    raise PlatformTimeoutError("Hook execution exceeded 5-second timeout")


def main() -> None:
    """Main entry point - Claude Code Hook script with GLOBAL TIMEOUT PROTECTION

    Receives the event name as a CLI argument and reads the JSON payload through stdin.
    Calls the handler appropriate for the event and outputs the results to stdout as JSON.
    Enforces a 5-second global timeout to prevent subprocess hangs from freezing Claude Code.

    🛠️ Usage:
        python alfred_hooks.py <event_name> < payload.json

    📣 Supported Events:
        - SessionStart: Start Session (display project status)
        - UserPromptSubmit: Prompt submission (JIT document loading)
        - SessionEnd, PreToolUse, PostToolUse, Notification, Stop, SubagentStop

    🚦 Exit Codes:
        - 0: Success
        - 1: Error (timeout, no arguments, JSON parsing failure, exception thrown)

    📝 Examples:
        $ echo '{"cwd": "."}' | python alfred_hooks.py SessionStart
        {"message": "🚀 MoAI-ADK Session Started\\n...", ...}

    🗒️ Notes:
        - Claude Code is automatically called (no need for direct user execution)
        - JSON I/O processing through stdin/stdout
        - Print error message to stderr
        - UserPromptSubmit uses a special output schema (hookEventName + additionalContext)
        - CRITICAL: 5-second global timeout prevents Claude Code freeze on subprocess hang

    🧪 TDD History:
        - RED: Event routing, JSON I/O, error handling testing
        - GREEN: Handler map-based routing implementation
        - REFACTOR: Error message clarification, exit code standardization, UserPromptSubmit schema separation
        - HOTFIX: Added global SIGALRM timeout to prevent subprocess hang (Issue #66)

    @TAG:HOOKS-TIMEOUT-001
    """
    # Set global 5-second timeout for entire hook execution
    signal.signal(signal.SIGALRM, _hook_timeout_handler)
    signal.alarm(5)

    try:
        # Check for event argument
        if len(sys.argv) < 2:
            print("Usage: alfred_hooks.py <event>", file=sys.stderr)
            sys.exit(1)

        event_name = sys.argv[1]

        try:
            # Read JSON from stdin
            input_data = sys.stdin.read()
            # Handle empty stdin gracefully (return empty dict)
            if not input_data or not input_data.strip():
                data = {}
            else:
                data = json.loads(input_data)

            cwd = data.get("cwd", ".")

            # Route to appropriate handler
            handlers = {
                "SessionStart": handle_session_start,
                "UserPromptSubmit": handle_user_prompt_submit,
                "SessionEnd": handle_session_end,
                "PreToolUse": handle_pre_tool_use,
                "PostToolUse": handle_post_tool_use,
                "Notification": handle_notification,
                "Stop": handle_stop,
                "SubagentStop": handle_subagent_stop,
            }

            handler = handlers.get(event_name)
            result = handler({"cwd": cwd, **data}) if handler else HookResult()

            # Output Hook result as JSON
            # Note: UserPromptSubmit uses to_user_prompt_submit_dict() for special schema
            if event_name == "UserPromptSubmit":
                print(json.dumps(result.to_user_prompt_submit_dict()))
            else:
                print(json.dumps(result.to_dict()))

            sys.exit(0)

        except json.JSONDecodeError as e:
            # Return valid Hook response even on JSON parse error
            error_response: dict[str, Any] = {
                "continue": True,
                "hookSpecificOutput": {"error": f"JSON parse error: {e}"},
            }
            print(json.dumps(error_response))
            print(f"JSON parse error: {e}", file=sys.stderr)
            sys.exit(1)
        except Exception as e:
            # Return valid Hook response even on unexpected error
            error_response: dict[str, Any] = {
                "continue": True,
                "hookSpecificOutput": {"error": f"Hook error: {e}"},
            }
            print(json.dumps(error_response))
            print(f"Unexpected error: {e}", file=sys.stderr)
            sys.exit(1)

    except PlatformTimeoutError:
        # CRITICAL: Hook took too long - return minimal valid response to prevent Claude Code freeze
        timeout_response: dict[str, Any] = {
            "continue": True,
            "systemMessage": "⚠️ Hook execution timeout - continuing without session info",
        }
        print(json.dumps(timeout_response))
        print("Hook timeout after 5 seconds", file=sys.stderr)
        sys.exit(1)

    finally:
        # Always cancel the alarm to prevent signal leakage
        signal.alarm(0)


if __name__ == "__main__":
    main()
