#!/usr/bin/env bash
#
# Mock gh CLI for testing GitHub API interactions
#
# This mock intercepts gh commands and returns predefined responses
# based on environment variables and fixture files.
#
# Environment variables:
#   MOCK_GH_FIXTURES_DIR - Directory containing response fixtures
#   MOCK_GH_PR_STATE - PR state (OPEN, CLOSED, MERGED)
#   MOCK_GH_PR_NUMBER - PR number
#   MOCK_GH_REACTIONS - JSON array of reactions
#   MOCK_GH_COMMENTS - JSON array of comments

set -euo pipefail

MOCK_GH_FIXTURES_DIR="${MOCK_GH_FIXTURES_DIR:-$(dirname "$0")/../fixtures}"
MOCK_GH_PR_STATE="${MOCK_GH_PR_STATE:-OPEN}"
MOCK_GH_PR_NUMBER="${MOCK_GH_PR_NUMBER:-123}"
MOCK_GH_HEAD_SHA="${MOCK_GH_HEAD_SHA:-abc123def456}"
MOCK_GH_LATEST_COMMIT_AT="${MOCK_GH_LATEST_COMMIT_AT:-2026-01-18T10:00:00Z}"

# Parse command
COMMAND="${1:-}"
shift || true

case "$COMMAND" in
    pr)
        SUBCOMMAND="${1:-}"
        shift || true
        case "$SUBCOMMAND" in
            view)
                # Parse flags - PR number may or may not be specified
                # Handle both: gh pr view 123 --json ... and gh pr view --json ...
                PR_NUM=""
                while [[ $# -gt 0 ]]; do
                    case "$1" in
                        --json)
                            FIELDS="$2"
                            shift 2
                            ;;
                        -q|--jq)
                            JQ_EXPR="$2"
                            shift 2
                            ;;
                        -*)
                            # Skip unknown flags
                            shift
                            ;;
                        *)
                            # Positional argument - assume it's PR number
                            PR_NUM="$1"
                            shift
                            ;;
                    esac
                done

                # Return based on requested fields
                if [[ "${FIELDS:-}" == "number,url" ]]; then
                    # For number,url query with jq '.number,.url', return newline-separated values
                    echo "{\"number\": $MOCK_GH_PR_NUMBER, \"url\": \"https://github.com/testowner/testrepo/pull/$MOCK_GH_PR_NUMBER\"}" | jq -r "${JQ_EXPR:-.}"
                elif [[ "${FIELDS:-}" == "number" ]]; then
                    echo "{\"number\": $MOCK_GH_PR_NUMBER}" | jq -r "${JQ_EXPR:-.}"
                elif [[ "${FIELDS:-}" == "state" ]]; then
                    echo "{\"state\": \"$MOCK_GH_PR_STATE\"}" | jq -r "${JQ_EXPR:-.}"
                elif [[ "${FIELDS:-}" == "headRefOid,commits" ]]; then
                    echo "{\"headRefOid\": \"$MOCK_GH_HEAD_SHA\", \"commits\": [{\"committedDate\": \"$MOCK_GH_LATEST_COMMIT_AT\"}]}" | jq -r "${JQ_EXPR:-.}"
                elif [[ "${FIELDS:-}" == "commits" ]]; then
                    echo "{\"commits\": [{\"committedDate\": \"$MOCK_GH_LATEST_COMMIT_AT\"}]}" | jq -r "${JQ_EXPR:-.}"
                else
                    echo "{\"number\": $MOCK_GH_PR_NUMBER, \"state\": \"$MOCK_GH_PR_STATE\", \"headRefOid\": \"$MOCK_GH_HEAD_SHA\"}"
                fi
                ;;

            comment)
                # Mock posting a comment
                PR_NUM="${1:-}"
                shift || true
                COMMENT_BODY=""

                while [[ $# -gt 0 ]]; do
                    case "$1" in
                        --body)
                            COMMENT_BODY="$2"
                            shift 2
                            ;;
                        *)
                            shift
                            ;;
                    esac
                done

                # Return success
                echo "Created comment on PR #$PR_NUM"
                ;;

            *)
                echo "Mock gh: Unknown pr subcommand: $SUBCOMMAND" >&2
                exit 1
                ;;
        esac
        ;;

    api)
        ENDPOINT="${1:-}"
        shift || true

        # Parse flags
        JQ_EXPR=""
        PAGINATE=false
        while [[ $# -gt 0 ]]; do
            case "$1" in
                --jq|-q)
                    JQ_EXPR="$2"
                    shift 2
                    ;;
                --paginate)
                    PAGINATE=true
                    shift
                    ;;
                *)
                    shift
                    ;;
            esac
        done

        # Route to appropriate fixture
        # IMPORTANT: More specific patterns must come BEFORE less specific ones
        case "$ENDPOINT" in
            user)
                echo "{\"login\": \"testuser\"}" | jq -r "${JQ_EXPR:-.}"
                ;;

            repos/*/issues/comments/*/reactions)
                # Return mock comment reactions (more specific - must come first)
                FIXTURE_FILE="$MOCK_GH_FIXTURES_DIR/comment-reactions.json"
                if [[ -f "$FIXTURE_FILE" ]]; then
                    cat "$FIXTURE_FILE" | jq -r "${JQ_EXPR:-.}"
                else
                    echo "[]"
                fi
                ;;

            repos/*/issues/*/reactions)
                # Return mock PR/issue reactions
                FIXTURE_FILE="$MOCK_GH_FIXTURES_DIR/reactions.json"
                if [[ -f "$FIXTURE_FILE" ]]; then
                    cat "$FIXTURE_FILE" | jq -r "${JQ_EXPR:-.}"
                else
                    echo "[]"
                fi
                ;;

            repos/*/issues/*/comments)
                # Return mock comments
                # If MOCK_GH_COMMENT_ID_LOOKUP_FAIL is set and jq is selecting by user.login,
                # return null to simulate failure to find the posted comment ID
                if [[ "${MOCK_GH_COMMENT_ID_LOOKUP_FAIL:-}" == "true" && "$JQ_EXPR" == *"select(.user.login"* ]]; then
                    echo "null"
                    exit 0
                fi
                FIXTURE_FILE="$MOCK_GH_FIXTURES_DIR/issue-comments.json"
                if [[ -f "$FIXTURE_FILE" ]]; then
                    cat "$FIXTURE_FILE" | jq -r "${JQ_EXPR:-.}"
                else
                    echo "[]"
                fi
                ;;

            repos/*/pulls/*/comments)
                # Return mock review comments
                FIXTURE_FILE="$MOCK_GH_FIXTURES_DIR/review-comments.json"
                if [[ -f "$FIXTURE_FILE" ]]; then
                    cat "$FIXTURE_FILE" | jq -r "${JQ_EXPR:-.}"
                else
                    echo "[]"
                fi
                ;;

            repos/*/pulls/*/reviews)
                # Return mock PR review submissions
                FIXTURE_FILE="$MOCK_GH_FIXTURES_DIR/pr-reviews.json"
                if [[ -f "$FIXTURE_FILE" ]]; then
                    cat "$FIXTURE_FILE" | jq -r "${JQ_EXPR:-.}"
                else
                    echo "[]"
                fi
                ;;

            *)
                echo "Mock gh: Unknown API endpoint: $ENDPOINT" >&2
                exit 1
                ;;
        esac
        ;;

    repo)
        SUBCOMMAND="${1:-}"
        shift || true
        case "$SUBCOMMAND" in
            view)
                # Parse flags
                FIELDS=""
                JQ_EXPR="."
                while [[ $# -gt 0 ]]; do
                    case "$1" in
                        --json) FIELDS="$2"; shift 2 ;;
                        -q|--jq) JQ_EXPR="$2"; shift 2 ;;
                        *) shift ;;
                    esac
                done
                # Return mock repo info
                if [[ "$FIELDS" == "owner" ]]; then
                    echo '{"owner": {"login": "testowner"}}' | jq -r "$JQ_EXPR"
                elif [[ "$FIELDS" == "name" ]]; then
                    echo '{"name": "testrepo"}' | jq -r "$JQ_EXPR"
                else
                    echo '{"owner": {"login": "testowner"}, "name": "testrepo"}'
                fi
                ;;
            *)
                echo "Mock gh: Unknown repo subcommand: $SUBCOMMAND" >&2
                exit 1
                ;;
        esac
        ;;

    auth)
        SUBCOMMAND="${1:-}"
        case "$SUBCOMMAND" in
            status)
                echo "Logged in to github.com as testuser"
                exit 0
                ;;
            *)
                echo "Mock gh: Unknown auth subcommand: $SUBCOMMAND" >&2
                exit 1
                ;;
        esac
        ;;

    *)
        echo "Mock gh: Unknown command: $COMMAND" >&2
        exit 1
        ;;
esac
