name: 'Util: Claude Task Runner'

on:
  workflow_dispatch:
    inputs:
      task:
        description: 'Task description - what should Claude do?'
        required: true
        type: string
      resumeUrl:
        description: 'Optional callback URL to call with the result when the workflow completes'
        required: false
        type: string
      model:
        description: 'Claude model to use (e.g., claude-opus-4-6, claude-sonnet-4-5, claude-haiku-4-5)'
        required: false
        type: string
        default: 'claude-sonnet-4-5-20250929'
      use_raw_prompt:
        description: 'Pass the task input directly as the prompt without wrapping it with guidelines and instructions'
        required: false
        type: boolean
        default: false
      max_turns:
        description: 'Maximum conversation turns before Claude stops gracefully'
        required: false
        type: number
        default: 50
      suppress_output:
        description: 'Suppress console output and job summary'
        required: false
        type: boolean
        default: true
      ref:
        description: 'Git ref (branch/tag/SHA) to check out and work on'
        required: false
        type: string
        default: 'master'

jobs:
  run-claude-task:
    runs-on: blacksmith-4vcpu-ubuntu-2204
    timeout-minutes: 60
    permissions:
      contents: write
      pull-requests: write
      issues: write

    steps:
      - name: Generate GitHub App Token
        id: generate_token
        uses: actions/create-github-app-token@29824e69f54612133e76f7eaac726eef6c875baf # v2.2.1
        with:
          app-id: ${{ secrets.N8N_ASSISTANT_APP_ID }}
          private-key: ${{ secrets.N8N_ASSISTANT_PRIVATE_KEY }}

      - name: Checkout repository
        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
        with:
          ref: ${{ inputs.ref }}
          fetch-depth: 1
          token: ${{ steps.generate_token.outputs.token }}

      - name: Configure git remote with token
        run: git remote set-url origin "https://x-access-token:${{ steps.generate_token.outputs.token }}@github.com/${{ github.repository }}.git"

      - name: Setup Node.js
        uses: ./.github/actions/setup-nodejs
        with:
          build-command: ''

      - name: Create working branch
        run: |
          BRANCH_NAME="claude/task-${{ github.run_id }}-${{ github.run_attempt }}"
          echo "BRANCH_NAME=$BRANCH_NAME" >> "$GITHUB_ENV"
          git checkout -b "$BRANCH_NAME"

      - name: Configure git author
        env:
          GH_ACTOR: ${{ github.actor }}
          GH_ACTOR_ID: ${{ github.actor_id }}
        run: |
          git config user.name "$GH_ACTOR"
          git config user.email "$GH_ACTOR_ID+$GH_ACTOR@users.noreply.github.com"
          echo "Git author configured as: $GH_ACTOR"

      - name: Prepare Claude prompt
        env:
          INPUT_TASK: ${{ inputs.task }}
          USE_RAW_PROMPT: ${{ inputs.use_raw_prompt }}
        run: node .github/scripts/claude-task/prepare-claude-prompt.mjs

      - name: Create MCP config
        env:
          MCP_LINEAR_API_KEY: ${{ secrets.MCP_LINEAR_API_KEY }}
          MCP_NOTION_TOKEN: ${{ secrets.MCP_NOTION_TOKEN }}
        run: |
          cat > /tmp/mcp-config.json << 'MCPEOF'
          {
            "mcpServers": {
              "linear": {
                "command": "npx",
                "args": [
                  "-y",
                  "mcp-remote",
                  "https://mcp.linear.app/sse",
                  "--header",
                  "Authorization:${AUTH_HEADER}"
                ],
                "env": {
                  "AUTH_HEADER": "Bearer MCP_LINEAR_API_KEY_PLACEHOLDER"
                }
              },
              "notion": {
                "command": "npx",
                "args": ["-y", "@notionhq/notion-mcp-server"],
                "env": {
                  "OPENAPI_MCP_HEADERS": "{\"Authorization\":\"Bearer MCP_NOTION_TOKEN_PLACEHOLDER\",\"Notion-Version\":\"2025-02-19\"}"
                }
              }
            }
          }
          MCPEOF
          sed -i "s|MCP_LINEAR_API_KEY_PLACEHOLDER|${MCP_LINEAR_API_KEY}|g" /tmp/mcp-config.json
          sed -i "s|MCP_NOTION_TOKEN_PLACEHOLDER|${MCP_NOTION_TOKEN}|g" /tmp/mcp-config.json

      - name: Run Claude
        id: claude
        continue-on-error: true
        uses: anthropics/claude-code-action@d668cc452deb931732f24c6b1bbf24d97bc0c586 # v1
        with:
          anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
          github_token: ${{ steps.generate_token.outputs.token }}
          prompt: ${{ env.CLAUDE_PROMPT }}
          show_full_output: ${{ inputs.suppress_output != true }}
          display_report: false
          plugin_marketplaces: "./.claude/plugins/n8n"
          plugins: "n8n@n8n"
          settings: |
            {
              "permissions": {
                "allow": [
                  "Bash",
                  "Read",
                  "Write",
                  "Edit",
                  "Glob",
                  "Grep",
                  "WebFetch",
                  "WebSearch",
                  "TodoWrite",
                  "Skill",
                  "Task",
                  "mcp__linear__*",
                  "mcp__notion__*"
                ]
              },
              "extraKnownMarketplaces": {
                "n8n": {
                  "source": {
                    "source": "directory",
                    "path": "./.claude/plugins/n8n"
                  }
                }
              },
              "enabledPlugins": {
                "n8n@n8n": true
              }
            }
          claude_args: |
            --model ${{ inputs.model }} --max-turns ${{ inputs.max_turns }} --mcp-config /tmp/mcp-config.json

      - name: Push branch
        if: always()
        env:
          REF: ${{ inputs.ref }}
        run: |
          if ! git diff --quiet "$REF" 2>/dev/null; then
            git push -u origin "$BRANCH_NAME"
            echo "::notice::Changes pushed to branch $BRANCH_NAME"
          else
            echo "::notice::No changes to push."
          fi

      - name: Summary
        if: always()
        env:
          CLAUDE_OUTCOME: ${{ steps.claude.outcome }}
          CLAUDE_SESSION_ID: ${{ steps.claude.outputs.session_id }}
        run: |
          {
            echo "## Claude Task Runner"
            echo "**Branch:** ${BRANCH_NAME:-N/A}"
            echo "**Claude outcome:** $CLAUDE_OUTCOME"
            if [ -n "$CLAUDE_SESSION_ID" ]; then
              echo "**Session ID:** \`$CLAUDE_SESSION_ID\`"
            fi
          } >> "$GITHUB_STEP_SUMMARY"

      - name: Call resume url
        if: always() && inputs.resumeUrl != ''
        env:
          RESUME_URL: ${{ inputs.resumeUrl }}
          EXECUTION_FILE: ${{ steps.claude.outputs.execution_file }}
          CLAUDE_OUTCOME: ${{ steps.claude.outcome }}
          CLAUDE_SESSION_ID: ${{ steps.claude.outputs.session_id }}
        run: node .github/scripts/claude-task/resume-callback.mjs

      - name: Check final status
        if: always()
        run: |
          if [ "${{ steps.claude.outcome }}" = "failure" ]; then
            echo "::error::Claude task failed. Check the 'Run Claude' step logs for details."
            exit 1
          fi
