#!/usr/bin/env sh
#
# This script is an example of an `aico` addon. Here's how it works:
#
# 1. DISCOVERY: `aico` finds this script because it's executable (`chmod +x`)
#    and located in the `./.aico/addons/` directory.
#
# 2. HELP TEXT: When `aico --help` is run, `aico` executes this script with
#    the `--usage` flag. The first line of output is used as the help text.
#
# 3. SESSION CONTEXT: `aico` sets the `AICO_SESSION_FILE` environment
#    variable, giving the addon the full path to the `.ai_session.json` file.
#    This addon doesn't need it, but others might.
#
# 4. DELEGATION: This addon delegates the core AI work back to `aico` by
#    calling `aico prompt --passthrough`. This is the recommended pattern for
#    complex addons, as it leverages `aico`'s features.
#
# 5. HISTORY MANAGEMENT: Before the commit is finalized, this addon calls `aico undo`
#    to immediately remove the commit-generation prompt and response from the main session
#    history. This ensures the history remains clean, even if the commit is aborted.

set -e

# --- Configuration ---
# The model to use for generating the commit message.
MODEL_NAME="openrouter/google/gemini-3-flash-preview"

# A list of authors.
# If populated, the first entry will be used as the primary commit author.
# All subsequent entries will be added as "Co-authored-by:" trailers.
# If empty, the default Git author will be used.
#
# Example:
# AUTHORS="Jane Doe <jane.doe@example.com>
# Sam Smith <sam.smith@example.com>"
AUTHORS=""
# --- End Configuration ---

# Check if --usage flag is passed and show help text
if [ "$1" = "--usage" ]; then
  echo "Generates a Conventional Commit message for staged changes." 
  exit 0
fi

# 1. Check for staged changes
if git diff --staged --quiet; then
  echo "No staged changes to commit."
  exit 0
fi

# 2. Gather Git context
GIT_DIFF_OUTPUT="$(git diff --staged --unified=0 --color=never)"
GIT_LOG_OUTPUT="$(git log --pretty=format:'%s' -n 20)"
AICO_CHAT_LOG="$(aico dump-history)"

# 3. Build the prompt
SYSTEM_PROMPT="You are an expert AI assistant named \`commit-bot\`. Your sole purpose is to generate a high-quality Git commit message in the Conventional Commit format. You are a tool, not a conversationalist. You have been given a git diff of staged changes, a recent git log, and a log of the developer's conversation with another AI assistant. Use all of this information to understand the 'why' behind the changes. The diff is the most important piece of context, as that is what will be committed. Ensure your generated message accurately and concisely summarizes all the changes present in the diff; do not omit any significant changes."

PROMPT=$(
  cat <<EOF
<chat_log>
$AICO_CHAT_LOG
</chat_log>

<git_diff>
$GIT_DIFF_OUTPUT
</git_diff>

<git_log>
$GIT_LOG_OUTPUT
</git_log>

<instructions>
Your task is to create a commit message based on the provided context. The message can be a single line, or include a brief body if the changes require more explanation. The context includes a git diff, a git log, and the conversation a developer had with an AI assistant (\`<chat_log>\`).

The commit message you generate will be used for the changes shown in the <git_diff> section.

<thinking_process>
1.  **Analyze the Diff**: Scrutinize the <git_diff> to identify the primary intent. Is it a new feature, a bug fix, a refactor, or something else? The diff reveals what changed, which is crucial for determining the type and scope.
2.  **Analyze the Chat Log**: Read the \`<chat_log>\` to understand the developer's reasoning and the "why" behind the changes. **CRITICAL**: The chat log often contains future plans or abandoned ideas. You MUST ignore anything in the chat log that is not physically reflected in the <git_diff>. Use the log only to explain the "why" of the existing diff.
3.  **Determine Type**: Based on your analysis, select the most appropriate type.
    - \`feat\`: A new feature.
    - \`fix\`: A bug fix.
    - Other allowed types: \`docs\`, \`style\`, \`refactor\`, \`perf\`, \`test\`, \`ci\`, \`chore\`.
4.  **Determine Scope**: Identify the primary module or component affected (e.g., \`api\`, \`auth\`, \`script\`). The scope MUST be a noun surrounded by parenthesis. If multiple areas are impacted, omit it.
5.  **Craft Message**: Write a short description of the code changes in the diff in the imperative mood (e.g., "add feature" not "added feature"). The description MUST immediately follow the colon and space.
6.  **Assemble Subject**: Combine these parts into the final \`<type>(<scope>): <message>\` format. The scope is optional.
7.  **Write Body (Optional)**: If the change is complex and the subject line is insufficient, add a concise body (1-2 sentences) explaining the 'why' behind the change. Use the \`<chat_log>\` for insights here. Separate the body from the subject with a single blank line.
</thinking_process>

<output_format>
- Produce a commit message that may include a subject and an optional body, separated by a blank line.
- The entire response must be ONLY the commit message text without xml tags.
</output_format>

<positive_examples>
- feat(routes): add list, import, and overview endpoints for v3 books
- fix(auth): correct password reset token validation
- fix(parser): handle multi-byte characters correctly

  The previous implementation failed when parsing UTF-8 encoded text containing multi-byte characters.
- refactor(services): simplify user creation logic
- docs(readme): update installation instructions
- chore(deps): update react to version 17.0.2
</positive_examples>

<negative_constraints>
- DO NOT use any other format than Conventional Commit.
- DO NOT add a period at the end of the subject line.
- DO NOT include any explanations, apologies, or extra text in your response.
- DO NOT wrap the output in backticks, quotes, or any other characters.
- DO NOT write a body unless the change is complex enough to warrant it.
- KEEP the body brief (1-2 sentences).
- DO NOT reference proposed changes, future plans, or logic discussed in the chat log if they do not appear in the staged <git_diff>.
- DO NOT return the thinking process or any other xml tags in the output.
</negative_constraints>
</instructions>
EOF
)

# 4. Invoke aico to get the commit message
AI_COMMIT_MSG=$(echo "$PROMPT" | aico prompt --passthrough --no-history --system-prompt "$SYSTEM_PROMPT" --model "$MODEL_NAME" 2>/dev/null)

# 5. Assemble the final commit message and execute git commit
# Use positional parameters to build arguments safely without eval
set -- -v --file - --edit
if [ -n "$AUTHORS" ]; then
  PRIMARY_AUTHOR=$(echo "$AUTHORS" | head -n 1)
  set -- "$@" "--author=$PRIMARY_AUTHOR"
fi

# 6. Clean up the history before committing
aico undo >/dev/null 2>&1

{
  echo "$AI_COMMIT_MSG"

  NUM_AUTHORS=$(echo "$AUTHORS" | grep -c . || true)
  if [ "$NUM_AUTHORS" -gt 1 ]; then
    echo "" # Blank line before trailers
    # Loop over co-authors (all except the first one)
    echo "$AUTHORS" | sed 1d | while IFS= read -r author; do
      if [ -n "$author" ]; then
        echo "Co-authored-by: $author"
      fi
    done
  fi
} | git commit "$@"
