//! Tool schema definitions for system operations, git, debug, wizard, and mesh tools.

use serde_json::{Value, json};

/// Returns tool schemas for system utilities, git operations, debug tools, wizard, and mesh.
pub(super) fn system_tools() -> Vec<Value> {
    vec![
        json!({
            "name": "get_server_logs",
            "description": "Return server log lines. By default reads from the in-process ring buffer (last 1000 entries). Pass from_file: true to read from the on-disk daily log files, which retain history beyond the ring buffer. The file path supports offset for pagination.",
            "inputSchema": {
                "type": "object",
                "properties": {
                    "lines": {
                        "type": "integer",
                        "description": "Number of lines to return (default 100; ring-buffer max 1000, file max 10000)"
                    },
                    "filter": {
                        "type": "string",
                        "description": "Optional substring filter applied to each log line (e.g. 'watcher', 'mcp', 'ERROR')"
                    },
                    "severity": {
                        "type": "string",
                        "description": "Ring-buffer only: filter by severity level ERROR, WARN, or INFO"
                    },
                    "from_file": {
                        "type": "boolean",
                        "description": "If true, read from on-disk daily log files instead of the in-memory ring. Supports older history and the offset parameter."
                    },
                    "offset": {
                        "type": "integer",
                        "description": "File mode only: skip the first N matching lines before returning results (for pagination)"
                    }
                }
            }
        }),
        json!({
            "name": "get_version",
            "description": "Return the server version, build hash, and running port.",
            "inputSchema": {
                "type": "object",
                "properties": {}
            }
        }),
        json!({
            "name": "prompt_permission",
            "description": "Present a permission request to the user via the web UI. Used by Claude Code's --permission-prompt-tool to delegate permission decisions to the frontend dialog. Returns on approval; returns an error on denial.",
            "inputSchema": {
                "type": "object",
                "properties": {
                    "tool_name": {
                        "type": "string",
                        "description": "The tool requesting permission (e.g. 'Bash', 'Write')"
                    },
                    "input": {
                        "type": "object",
                        "description": "The tool's input arguments"
                    }
                },
                "required": ["tool_name", "input"]
            }
        }),
        json!({
            "name": "get_token_usage",
            "description": "Return per-agent token usage records from the persistent log. Shows input tokens, output tokens, cache tokens, and cost in USD for each agent session. Optionally filter by story_id.",
            "inputSchema": {
                "type": "object",
                "properties": {
                    "story_id": {
                        "type": "string",
                        "description": "Optional: filter records to a specific story (e.g. '42_my_story')"
                    }
                }
            }
        }),
        json!({
            "name": "run_command",
            "description": "Execute a shell command in an agent's worktree directory. The working_dir must be inside .huskies/worktrees/. Returns stdout, stderr, exit_code, and timed_out. Supports SSE streaming (send Accept: text/event-stream) for long-running commands. Dangerous commands (rm -rf /, sudo, etc.) are blocked.",
            "inputSchema": {
                "type": "object",
                "properties": {
                    "command": {
                        "type": "string",
                        "description": "The bash command to execute (passed to bash -c)"
                    },
                    "working_dir": {
                        "type": "string",
                        "description": "Absolute path to the worktree directory to run the command in. Must be inside .huskies/worktrees/."
                    },
                    "timeout": {
                        "type": "integer",
                        "description": "Timeout in seconds (default: 120, max: 600)"
                    }
                },
                "required": ["command", "working_dir"]
            }
        }),
        json!({
            "name": "run_tests",
            "description": "Run the project's test suite (script/test). Blocks server-side until tests finish (up to 20 minutes) and returns the full result {passed, exit_code, timed_out, tests_passed, tests_failed, output}. No polling needed; do NOT call get_test_result for the same job — that tool exists only for external observers.",
            "inputSchema": {
                "type": "object",
                "properties": {
                    "worktree_path": {
                        "type": "string",
                        "description": "Optional absolute path to a worktree to run tests in. Must be inside .huskies/worktrees/. Defaults to the project root."
                    }
                },
                "required": []
            }
        }),
        json!({
            "name": "get_test_result",
            "description": "Check on a running test job started by run_tests. Returns {\"status\": \"running\", \"elapsed_secs\": N} if still in progress, or the full test result (passed, exit_code, test counts, output) if finished.",
            "inputSchema": {
                "type": "object",
                "properties": {
                    "worktree_path": {
                        "type": "string",
                        "description": "Optional absolute path to the worktree. Must match the worktree_path used in run_tests."
                    }
                },
                "required": []
            }
        }),
        json!({
            "name": "run_build",
            "description": "Run the project's build script (script/build) in the given worktree and return the result as truncated JSON with passed, exit_code, and output fields.",
            "inputSchema": {
                "type": "object",
                "properties": {
                    "worktree_path": {
                        "type": "string",
                        "description": "Optional absolute path to a worktree to run the build in. Must be inside .huskies/worktrees/. Defaults to the project root."
                    }
                },
                "required": []
            }
        }),
        json!({
            "name": "run_lint",
            "description": "Run the project's lint script (script/lint) in the given worktree and return the result as truncated JSON with passed, exit_code, and output fields.",
            "inputSchema": {
                "type": "object",
                "properties": {
                    "worktree_path": {
                        "type": "string",
                        "description": "Optional absolute path to a worktree to run lint in. Must be inside .huskies/worktrees/. Defaults to the project root."
                    }
                },
                "required": []
            }
        }),
        json!({
            "name": "run_check",
            "description": "Run script/check (cargo check --tests --workspace) in the agent's worktree for fast compile-only feedback. Returns the full, untruncated output so every compiler diagnostic is visible. Much faster than run_tests — use this while iterating to catch compile errors; call run_tests only to validate the full pipeline before committing.",
            "inputSchema": {
                "type": "object",
                "properties": {
                    "worktree_path": {
                        "type": "string",
                        "description": "Optional absolute path to a worktree to run the check in. Must be inside .huskies/worktrees/. Defaults to the project root."
                    }
                },
                "required": []
            }
        }),
        json!({
            "name": "edit",
            "description": "Replace old_string with new_string in a file inside the agent's assigned worktree. Mirrors Claude's built-in Edit tool but validates that file_path is inside .huskies/worktrees/ to prevent writes to the master worktree. By default replaces the first occurrence only; set replace_all to true to replace every occurrence.",
            "inputSchema": {
                "type": "object",
                "properties": {
                    "file_path": {
                        "type": "string",
                        "description": "Absolute path to the file to edit. Must be inside .huskies/worktrees/."
                    },
                    "old_string": {
                        "type": "string",
                        "description": "The exact string to replace."
                    },
                    "new_string": {
                        "type": "string",
                        "description": "The replacement string."
                    },
                    "replace_all": {
                        "type": "boolean",
                        "description": "If true, replace every occurrence of old_string. Default: false (replace first occurrence only)."
                    }
                },
                "required": ["file_path", "old_string", "new_string"]
            }
        }),
        json!({
            "name": "write",
            "description": "Write content to a file inside the agent's assigned worktree, creating the file (and any missing parent directories) if necessary. Mirrors Claude's built-in Write tool but validates that file_path is inside .huskies/worktrees/ to prevent writes to the master worktree.",
            "inputSchema": {
                "type": "object",
                "properties": {
                    "file_path": {
                        "type": "string",
                        "description": "Absolute path to the file to write. Must be inside .huskies/worktrees/."
                    },
                    "content": {
                        "type": "string",
                        "description": "The content to write to the file."
                    }
                },
                "required": ["file_path", "content"]
            }
        }),
        json!({
            "name": "git_status",
            "description": "Return the working tree status of an agent's worktree (staged, unstaged, and untracked files). The worktree_path must be inside .huskies/worktrees/. Push and remote operations are not available.",
            "inputSchema": {
                "type": "object",
                "properties": {
                    "worktree_path": {
                        "type": "string",
                        "description": "Absolute path to the worktree directory. Must be inside .huskies/worktrees/."
                    }
                },
                "required": ["worktree_path"]
            }
        }),
        json!({
            "name": "git_diff",
            "description": "Return diff output for an agent's worktree. Supports unstaged (default), staged, or a commit range. The worktree_path must be inside .huskies/worktrees/.",
            "inputSchema": {
                "type": "object",
                "properties": {
                    "worktree_path": {
                        "type": "string",
                        "description": "Absolute path to the worktree directory. Must be inside .huskies/worktrees/."
                    },
                    "staged": {
                        "type": "boolean",
                        "description": "If true, show staged diff (--staged). Default: false."
                    },
                    "commit_range": {
                        "type": "string",
                        "description": "Optional commit range (e.g. 'HEAD~3..HEAD', 'abc123..def456')."
                    }
                },
                "required": ["worktree_path"]
            }
        }),
        json!({
            "name": "git_add",
            "description": "Stage files by path in an agent's worktree. The worktree_path must be inside .huskies/worktrees/.",
            "inputSchema": {
                "type": "object",
                "properties": {
                    "worktree_path": {
                        "type": "string",
                        "description": "Absolute path to the worktree directory. Must be inside .huskies/worktrees/."
                    },
                    "paths": {
                        "type": "array",
                        "items": { "type": "string" },
                        "description": "List of file paths to stage (relative to worktree_path)."
                    }
                },
                "required": ["worktree_path", "paths"]
            }
        }),
        json!({
            "name": "git_commit",
            "description": "Commit staged changes in an agent's worktree with the given message. The worktree_path must be inside .huskies/worktrees/. Push and remote operations are not available.",
            "inputSchema": {
                "type": "object",
                "properties": {
                    "worktree_path": {
                        "type": "string",
                        "description": "Absolute path to the worktree directory. Must be inside .huskies/worktrees/."
                    },
                    "message": {
                        "type": "string",
                        "description": "Commit message."
                    }
                },
                "required": ["worktree_path", "message"]
            }
        }),
        json!({
            "name": "git_log",
            "description": "Return commit history for an agent's worktree with configurable count and format. The worktree_path must be inside .huskies/worktrees/.",
            "inputSchema": {
                "type": "object",
                "properties": {
                    "worktree_path": {
                        "type": "string",
                        "description": "Absolute path to the worktree directory. Must be inside .huskies/worktrees/."
                    },
                    "count": {
                        "type": "integer",
                        "description": "Number of commits to return (default: 10, max: 500)."
                    },
                    "format": {
                        "type": "string",
                        "description": "git pretty-format string (default: '%H%x09%s%x09%an%x09%ai')."
                    }
                },
                "required": ["worktree_path"]
            }
        }),
        json!({
            "name": "loc_file",
            "description": "Return the line count for a specific file. Path is resolved relative to the project root. Returns an error if the file does not exist.",
            "inputSchema": {
                "type": "object",
                "properties": {
                    "file_path": {
                        "type": "string",
                        "description": "Path to the file, relative to the project root (e.g. 'server/src/main.rs')"
                    }
                },
                "required": ["file_path"]
            }
        }),
        json!({
            "name": "dump_crdt",
            "description": "DEBUG TOOL: Dump the raw in-memory CRDT state. Returns every item the running server knows about, including tombstoned (deleted) entries, with internal op metadata (content_index, is_deleted, stage, etc.). Use this when diagnosing CRDT/state divergence — NOT for normal pipeline introspection (use get_pipeline_status for that). Optional story_id filter returns a single item.",
            "inputSchema": {
                "type": "object",
                "properties": {
                    "story_id": {
                        "type": "string",
                        "description": "Optional: restrict output to this single work item identifier (filename stem, e.g. '42_story_my_feature')"
                    }
                },
                "required": []
            }
        }),
        json!({
            "name": "wizard_status",
            "description": "Return the current setup wizard state: which step is active, and which are done/skipped/pending. Use this to inspect progress before calling wizard_generate, wizard_confirm, wizard_skip, or wizard_retry.",
            "inputSchema": {
                "type": "object",
                "properties": {}
            }
        }),
        json!({
            "name": "wizard_generate",
            "description": "Drive content generation for the current wizard step. Call with no arguments to mark the step as 'generating' and receive a hint about what to produce. Call again with a 'content' argument (the full file body you generated) to stage it for review. Content is NOT written to disk until wizard_confirm is called.",
            "inputSchema": {
                "type": "object",
                "properties": {
                    "content": {
                        "type": "string",
                        "description": "The generated file content to stage for the current step. Omit to receive a generation hint and mark the step as generating."
                    }
                }
            }
        }),
        json!({
            "name": "wizard_confirm",
            "description": "Confirm the current wizard step: writes any staged content to disk (only if the target file does not already exist) and advances to the next step. Existing files are never overwritten.",
            "inputSchema": {
                "type": "object",
                "properties": {}
            }
        }),
        json!({
            "name": "wizard_skip",
            "description": "Skip the current wizard step without writing any file. Use when a step does not apply to this project.",
            "inputSchema": {
                "type": "object",
                "properties": {}
            }
        }),
        json!({
            "name": "wizard_retry",
            "description": "Discard any staged content for the current wizard step and reset it to pending so it can be regenerated. Use when the generated content needs improvement.",
            "inputSchema": {
                "type": "object",
                "properties": {}
            }
        }),
        json!({
            "name": "mesh_status",
            "description": "Return read-only peer mesh status: the local node id and a list of known peers, each with node_id, pubkey, last_seen timestamp, and is_self flag. Does not mutate state.",
            "inputSchema": {
                "type": "object",
                "properties": {}
            }
        }),
        json!({
            "name": "schedule_event_trigger",
            "description": "Register an event-based pipeline trigger that fires when a TransitionFired event matches the given predicate. Persists across server restarts. Returns the trigger id.",
            "inputSchema": {
                "type": "object",
                "properties": {
                    "predicate": {
                        "type": "object",
                        "description": "Conditions that must all match for the trigger to fire. Omit a field to match any value (wildcard).",
                        "properties": {
                            "story_id": { "type": "string", "description": "Match only transitions for this story id (e.g. '42_my_feature')." },
                            "from_stage": { "type": "string", "description": "Match only when the stage before the transition equals this label (e.g. 'Merge', 'Coding')." },
                            "to_stage": { "type": "string", "description": "Match only when the stage after the transition equals this label (e.g. 'Done', 'MergeFailure')." },
                            "event_kind": { "type": "string", "description": "Match only when the PipelineEvent kind equals this label (e.g. 'MergeFailed', 'Block', 'MergeSucceeded')." }
                        }
                    },
                    "action": {
                        "type": "object",
                        "description": "What to do when the trigger fires.",
                        "properties": {
                            "type": { "type": "string", "enum": ["mcp", "prompt"], "description": "\"mcp\": call an MCP tool (no LLM). \"prompt\": spawn a focused agent with the text as its task." },
                            "method": { "type": "string", "description": "For type=mcp: the MCP tool name to call (e.g. 'get_pipeline_status')." },
                            "args": { "type": "object", "description": "For type=mcp: arguments to pass to the tool." },
                            "text": { "type": "string", "description": "For type=prompt: the task text for the spawned agent." }
                        },
                        "required": ["type"]
                    },
                    "mode": {
                        "type": "string",
                        "enum": ["once", "persistent"],
                        "description": "\"once\" (default): remove the trigger after it fires once. \"persistent\": keep it active until cancel_event_trigger is called."
                    }
                },
                "required": ["predicate", "action"]
            }
        }),
        json!({
            "name": "list_event_triggers",
            "description": "Return all currently registered event triggers with their ids, predicates, actions, and fire modes.",
            "inputSchema": {
                "type": "object",
                "properties": {}
            }
        }),
        json!({
            "name": "cancel_event_trigger",
            "description": "Cancel and remove a registered event trigger by its id.",
            "inputSchema": {
                "type": "object",
                "properties": {
                    "id": {
                        "type": "string",
                        "description": "The trigger id returned by schedule_event_trigger."
                    }
                },
                "required": ["id"]
            }
        }),
        json!({
            "name": "find_orphaned_items",
            "description": "Find half-written (orphaned) pipeline items: story IDs that exist in the content store but have no live CRDT entry. These are invisible to all normal read paths (list_refactors, get_pipeline_status, etc.) and result from the bug 1001 split-brain race. Returns a list of orphaned IDs with their names and tombstone status. Use recover_half_written_items to fix them.",
            "inputSchema": {
                "type": "object",
                "properties": {}
            }
        }),
        json!({
            "name": "schedule_timer",
            "description": "Register a durable scheduled timer that fires an MCP call or reminder at a specified time. Survives server restart and rebuild. Use 'once' for a one-shot timer or 'recurring' to re-arm automatically after each fire.",
            "inputSchema": {
                "type": "object",
                "properties": {
                    "when": {
                        "type": "string",
                        "description": "When to fire: relative duration ('in 2 hours', '15 minutes', '30s') or ISO 8601 absolute timestamp ('2026-05-15T10:00:00Z')"
                    },
                    "action": {
                        "type": "object",
                        "description": "What to do when the timer fires. Either {\"type\":\"mcp\",\"method\":\"tool_name\",\"args\":{...}} for an MCP call or {\"type\":\"prompt\",\"text\":\"...\"} for a server-log reminder.",
                        "properties": {
                            "type": { "type": "string", "enum": ["mcp", "prompt"] },
                            "method": { "type": "string", "description": "MCP tool name (required for type='mcp')" },
                            "args": { "type": "object", "description": "MCP tool arguments (for type='mcp')" },
                            "text": { "type": "string", "description": "Reminder text (required for type='prompt')" }
                        },
                        "required": ["type"]
                    },
                    "mode": {
                        "type": "string",
                        "enum": ["once", "recurring"],
                        "description": "Fire once (default) or keep recurring. For recurring with absolute 'when', also provide 'interval'."
                    },
                    "interval": {
                        "type": "string",
                        "description": "Re-arm interval for recurring timers when 'when' is an absolute timestamp (e.g. '24h', '1 hour', '30 minutes'). Optional when 'when' is relative — interval is inferred."
                    },
                    "label": {
                        "type": "string",
                        "description": "Optional human-readable label shown in list_timers output."
                    }
                },
                "required": ["when", "action"]
            }
        }),
        json!({
            "name": "list_timers",
            "description": "List all pending scheduled timers registered via schedule_timer.",
            "inputSchema": {
                "type": "object",
                "properties": {}
            }
        }),
        json!({
            "name": "cancel_timer",
            "description": "Cancel a scheduled timer by its ID. Use list_timers to find the ID.",
            "inputSchema": {
                "type": "object",
                "properties": {
                    "id": {
                        "type": "string",
                        "description": "Timer ID to cancel (e.g. 'tm-a3f7b9c2')"
                    }
                },
                "required": ["id"]
            }
        }),
        json!({
            "name": "recover_half_written_items",
            "description": "Recover half-written (orphaned) pipeline items by lifting each onto a fresh non-tombstoned ID. For each orphan, allocates a new ID, copies the content, re-applies item_type and depends_on from front matter, verifies the new entry is live in the CRDT, then removes the orphaned row. Pass 'only' to restrict recovery to specific orphan IDs (safe for live systems); omit to recover all. Returns old_id → new_id mappings for every successful recovery.",
            "inputSchema": {
                "type": "object",
                "properties": {
                    "only": {
                        "type": "array",
                        "items": { "type": "string" },
                        "description": "Optional: restrict recovery to these specific orphan IDs (e.g. ['1000', '999']). Omit to recover all orphans."
                    }
                }
            }
        }),
    ]
}
