#!/usr/bin/env bash

# TaskSentinel Claude Code Hook 适配器
# 将 Claude Code hooks 的数据格式转换为 TaskSentinel 脚本期望的格式
# 支持显示完整的 Claude Code 钩子信息
# Copyright (c) 2025 TaskSentinel
# MIT License

set -euo pipefail

# 脚本信息
readonly SCRIPT_NAME="$(basename "$0")"
readonly SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
readonly PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"

# 处理Claude Code钩子数据
process_claude_hook() {
    local hook_event_name="$HOOK_EVENT_NAME"
    local session_id=$(echo "$INPUT_DATA" | jq -r '.session_id // "unknown"' 2>/dev/null)
    local transcript_path=$(echo "$INPUT_DATA" | jq -r '.transcript_path // empty' 2>/dev/null)
    local cwd=$(echo "$INPUT_DATA" | jq -r '.cwd // empty' 2>/dev/null)
    
    # 如果没有cwd，使用当前目录
    if [[ -z "$cwd" ]]; then
        cwd=$(pwd)
    fi
    
    # 根据钩子事件类型处理
    case "$hook_event_name" in
        "PreToolUse")
            process_pre_tool_use
            ;;
        "PostToolUse")  
            process_post_tool_use
            ;;
        "Notification")
            process_notification
            ;;
        "UserPromptSubmit")
            process_user_prompt_submit
            ;;
        "Stop")
            process_stop
            ;;
        "SubagentStop")
            process_subagent_stop
            ;;
        "PreCompact")
            process_pre_compact
            ;;
        *)
            process_unknown_hook
            ;;
    esac
}

# 处理PreToolUse钩子
process_pre_tool_use() {
    local tool_name=$(echo "$INPUT_DATA" | jq -r '.tool_name // "unknown"' 2>/dev/null)
    local tool_input=$(echo "$INPUT_DATA" | jq -c '.tool_input // {}' 2>/dev/null)
    
    local message="⚙️ Claude Code准备执行工具: $tool_name"
    local event_type="info"
    
    # 根据工具类型调整事件类型和消息
    case "$tool_name" in
        "Bash")
            event_type="warning"
            local command=$(echo "$tool_input" | jq -r '.command // empty' 2>/dev/null)
            if [[ -n "$command" ]]; then
                message="⚙️ Claude Code准备执行命令: $command"
            fi
            ;;
        "Write"|"Edit"|"MultiEdit")
            event_type="info"
            local file_path=$(echo "$tool_input" | jq -r '.file_path // empty' 2>/dev/null)
            if [[ -n "$file_path" ]]; then
                message="⚙️ Claude Code准备修改文件: $file_path"
            fi
            ;;
        "Read")
            event_type="info"
            local file_path=$(echo "$tool_input" | jq -r '.file_path // empty' 2>/dev/null)
            if [[ -n "$file_path" ]]; then
                message="⚙️ Claude Code准备读取文件: $file_path"
            fi
            ;;
        "Task")
            event_type="info"
            message="⚙️ Claude Code准备启动子代理任务"
            ;;
    esac
    
    build_and_send_notification "$message" "$event_type"
}

# 处理PostToolUse钩子  
process_post_tool_use() {
    local tool_name=$(echo "$INPUT_DATA" | jq -r '.tool_name // "unknown"' 2>/dev/null)
    local tool_response=$(echo "$INPUT_DATA" | jq -c '.tool_response // {}' 2>/dev/null)
    
    # 检查工具执行是否成功
    local success=$(echo "$tool_response" | jq -r '.success // true' 2>/dev/null)
    local message="✅ Claude Code已完成工具执行: $tool_name"
    local event_type="task_complete"
    
    if [[ "$success" == "false" ]]; then
        message="❌ Claude Code工具执行失败: $tool_name"
        event_type="error"
    fi
    
    # 根据工具类型调整消息
    case "$tool_name" in
        "Bash")
            if [[ "$success" == "false" ]]; then
                message="❌ Claude Code命令执行失败"
                event_type="error"
            else
                message="✅ Claude Code命令执行成功"
                event_type="task_complete"
            fi
            ;;
        "Write"|"Edit"|"MultiEdit")
            local file_path=$(echo "$tool_response" | jq -r '.filePath // .file_path // empty' 2>/dev/null)
            if [[ -n "$file_path" ]]; then
                if [[ "$success" == "false" ]]; then
                    message="❌ Claude Code文件修改失败: $file_path"
                    event_type="error"
                else
                    message="✅ Claude Code文件修改完成: $file_path"
                    event_type="task_complete"
                fi
            fi
            ;;
    esac
    
    build_and_send_notification "$message" "$event_type"
}

# 处理Notification钩子
process_notification() {
    local notification_message=$(echo "$INPUT_DATA" | jq -r '.message // "Claude Code通知"' 2>/dev/null)
    local message="🔔 Claude Code通知: $notification_message"
    local event_type="info"
    
    build_and_send_notification "$message" "$event_type"
}

# 处理UserPromptSubmit钩子
process_user_prompt_submit() {
    local user_prompt=$(echo "$INPUT_DATA" | jq -r '.prompt // empty' 2>/dev/null)
    local message="📝 用户提交了新的提示请求"
    local event_type="info"
    
    # 如果提示内容过长，只显示前100个字符
    if [[ -n "$user_prompt" && ${#user_prompt} -gt 100 ]]; then
        local prompt_preview="${user_prompt:0:100}..."
        message="📝 用户提交提示: $prompt_preview"
    elif [[ -n "$user_prompt" ]]; then
        message="📝 用户提交提示: $user_prompt"
    fi
    
    build_and_send_notification "$message" "$event_type"
}

# 处理Stop钩子
process_stop() {
    local stop_hook_active=$(echo "$INPUT_DATA" | jq -r '.stop_hook_active // false' 2>/dev/null)
    local message="⏹️ Claude Code主代理已停止响应"
    local event_type="task_complete"
    
    if [[ "$stop_hook_active" == "true" ]]; then
        message="⏹️ Claude Code主代理停止（钩子已激活）"
    fi
    
    build_and_send_notification "$message" "$event_type"
}

# 处理SubagentStop钩子
process_subagent_stop() {
    local stop_hook_active=$(echo "$INPUT_DATA" | jq -r '.stop_hook_active // false' 2>/dev/null)
    local message="⏸️ Claude Code子代理已停止响应"
    local event_type="task_complete"
    
    if [[ "$stop_hook_active" == "true" ]]; then
        message="⏸️ Claude Code子代理停止（钩子已激活）"
    fi
    
    build_and_send_notification "$message" "$event_type"
}

# 处理PreCompact钩子
process_pre_compact() {
    local trigger=$(echo "$INPUT_DATA" | jq -r '.trigger // "unknown"' 2>/dev/null)
    local custom_instructions=$(echo "$INPUT_DATA" | jq -r '.custom_instructions // empty' 2>/dev/null)
    
    local message="🗁️ Claude Code准备执行压缩操作"
    local event_type="info"
    
    case "$trigger" in
        "manual")
            message="🗁️ Claude Code准备执行手动压缩操作"
            ;;
        "auto")
            message="🗁️ Claude Code准备执行自动压缩操作（上下文窗口已满）"
            event_type="warning"
            ;;
    esac
    
    build_and_send_notification "$message" "$event_type"
}

# 处理未知钩子事件
process_unknown_hook() {
    local message="🔌 Claude Code钩子事件: $HOOK_EVENT_NAME"
    local event_type="info"
    
    build_and_send_notification "$message" "$event_type"
}

# 构建并发送通知到TaskSentinel
build_and_send_notification() {
    local message="$1"
    local event_type="$2"
    local cwd=$(echo "$INPUT_DATA" | jq -r '.cwd // empty' 2>/dev/null)
    
    if [[ -z "$cwd" ]]; then
        cwd=$(pwd)
    fi
    
    # 构建TaskSentinel期望的JSON格式，包含完整的原始数据
    local task_sentinel_json
    task_sentinel_json=$(cat << EOF
{
  "message": "$message",
  "event": "$event_type", 
  "cwd": "$cwd",
  "original_hook_data": $INPUT_DATA
}
EOF
)
    
    # 将转换后的数据传递给TaskSentinel脚本
    # 优先使用已安装的版本，如果不存在则使用项目中的版本
    if command -v tasksentry >/dev/null 2>&1; then
        echo "$task_sentinel_json" | tasksentry
    elif [[ -f "$PROJECT_ROOT/scripts/tasksentry.sh" ]]; then
        echo "$task_sentinel_json" | "$PROJECT_ROOT/scripts/tasksentry.sh"
    else
        echo "错误: 找不到 TaskSentinel 脚本" >&2
        exit 1
    fi
}

# 主执行逻辑
main() {
    # 读取 Claude Code hook 传入的数据
    INPUT_DATA=""
    if [[ ! -t 0 ]]; then
        INPUT_DATA=$(cat)
    fi

    # 如果没有输入数据，创建默认消息
    if [[ -z "$INPUT_DATA" ]]; then
        INPUT_DATA='{"hook_event_name": "unknown", "message": "Claude Code 事件触发"}'
    fi

    # 检查输入是否为有效的JSON
    if ! echo "$INPUT_DATA" | jq empty >/dev/null 2>&1; then
        # 如果不是JSON，创建一个包含原始内容的JSON结构
        ESCAPED_INPUT=$(echo "$INPUT_DATA" | sed 's/\\/\\\\/g; s/"/\\"/g')
        INPUT_DATA="{\"message\": \"$ESCAPED_INPUT\", \"event\": \"info\"}"
    fi

    # 检查是否是Claude Code钩子格式
    HOOK_EVENT_NAME=$(echo "$INPUT_DATA" | jq -r '.hook_event_name // empty' 2>/dev/null)

    if [[ -n "$HOOK_EVENT_NAME" ]]; then
        # Claude Code钩子格式 - 调用专门的处理函数
        process_claude_hook
    else
        # 传统格式 - 直接传递给TaskSentinel
        # 优先使用已安装的版本，如果不存在则使用项目中的版本
        if command -v tasksentry >/dev/null 2>&1; then
            echo "$INPUT_DATA" | tasksentry
        elif [[ -f "$PROJECT_ROOT/scripts/tasksentry.sh" ]]; then
            echo "$INPUT_DATA" | "$PROJECT_ROOT/scripts/tasksentry.sh"
        else
            echo "错误: 找不到 TaskSentinel 脚本" >&2
            exit 1
        fi
    fi
}

# 执行主函数
main "$@"