#!/bin/bash
set -euo pipefail

GITEA_TOKEN_FILE="${GITEA_TOKEN_FILE:-$HOME/.config/gitea/token}"

function usage() {
    echo "Usage: gitea-pr create [--title TITLE] [--body BODY] [--base BRANCH]"
    echo "       gitea-pr comments PR_NUMBER"
    echo "       gitea-pr merge PR_NUMBER"
    echo ""
    echo "Requires GITEA_SSH_HOST and GITEA_API set in the environment (e.g. in" \
         "your shell profile), and a token at $GITEA_TOKEN_FILE (or GITEA_TOKEN" \
         "set for this invocation only)."
}

function require_config() {
    if [ -z "${GITEA_SSH_HOST:-}" ]; then
        echo "GITEA_SSH_HOST is not set. Add 'export GITEA_SSH_HOST=<gitea ssh hostname>'" \
             "(e.g. gitbox.bradina.localdomain) to ~/.profile.local" >&2
        exit 1
    fi
    if [ -z "${GITEA_API:-}" ]; then
        echo "GITEA_API is not set. Add 'export GITEA_API=https://<gitea host>/api/v1'" \
             "(e.g. https://gitbox.branderson.io/api/v1) to ~/.profile.local" >&2
        exit 1
    fi
}

function require_token() {
    if [ -z "${GITEA_TOKEN:-}" ] && [ -f "$GITEA_TOKEN_FILE" ]; then
        GITEA_TOKEN=$(<"$GITEA_TOKEN_FILE")
    fi
    if [ -z "${GITEA_TOKEN:-}" ]; then
        echo "No Gitea token found. Generate one in the Gitea web UI" \
             "(Settings > Applications, scopes write:repository + write:issue)" \
             "and save it to $GITEA_TOKEN_FILE (chmod 600), or set GITEA_TOKEN" \
             "in the environment for this invocation only." >&2
        exit 1
    fi
}

function gitea_owner_repo() {
    local remote_url host owner_repo
    remote_url=$(git remote get-url origin 2>/dev/null) || {
        echo "No 'origin' remote found in this repository" >&2
        exit 1
    }
    host=$(echo "$remote_url" | sed -E 's#^[^@]+@([^:]+):.*#\1#')
    if [ "$host" != "$GITEA_SSH_HOST" ]; then
        echo "origin remote ($remote_url) is not on $GITEA_SSH_HOST; gitea-pr only supports this host" >&2
        exit 1
    fi
    owner_repo=$(echo "$remote_url" | sed -E 's#^[^@]+@[^:]+:##; s#\.git$##')
    echo "$owner_repo"
}

if [ "$#" -lt 1 ]; then
    usage
    exit 1
fi

subcommand="$1"
shift

case "$subcommand" in
    create|comments|merge)
        require_config
        require_token
        owner_repo=$(gitea_owner_repo)
        owner="${owner_repo%%/*}"
        repo="${owner_repo##*/}"
        ;;
    *)
        usage
        exit 1
        ;;
esac

case "$subcommand" in
    create)
        title=""
        body=""
        base=""
        while [ "$#" -gt 0 ]; do
            case "$1" in
                --title) title="$2"; shift 2 ;;
                --body) body="$2"; shift 2 ;;
                --base) base="$2"; shift 2 ;;
                *) echo "Unknown option: $1" >&2; usage; exit 1 ;;
            esac
        done

        current_branch=$(git rev-parse --abbrev-ref HEAD)
        if [ "$current_branch" = "HEAD" ]; then
            echo "Detached HEAD: check out the feature branch before creating a PR" >&2
            exit 1
        fi

        response=$(curl -sS -w '\n%{http_code}' "${GITEA_API}/repos/${owner}/${repo}/pulls?state=open" \
            -H "Authorization: token ${GITEA_TOKEN}")
        http_code=$(echo "$response" | tail -1)
        json=$(echo "$response" | sed '$d')
        if [ "$http_code" -lt 200 ] || [ "$http_code" -ge 300 ]; then
            echo "Failed to check for an existing PR (HTTP $http_code):" >&2
            echo "$json" >&2
            exit 1
        fi
        existing_url=$(echo "$json" | jq -r --arg head "$current_branch" \
            '.[] | select(.head.ref == $head) | .html_url' | head -1)
        if [ -n "$existing_url" ]; then
            echo "$existing_url"
            exit 0
        fi

        if [ -z "$base" ]; then
            base=$(git symbolic-ref refs/remotes/origin/HEAD 2>/dev/null | sed 's#refs/remotes/origin/##' || true)
            base="${base:-main}"
        fi
        if [ -z "$title" ]; then
            title="$current_branch"
        fi

        response=$(curl -sS -w '\n%{http_code}' -X POST "${GITEA_API}/repos/${owner}/${repo}/pulls" \
            -H "Authorization: token ${GITEA_TOKEN}" \
            -H "Content-Type: application/json" \
            -d "$(jq -n --arg head "$current_branch" --arg base "$base" --arg title "$title" --arg body "$body" \
                '{head: $head, base: $base, title: $title, body: $body}')")
        http_code=$(echo "$response" | tail -1)
        json=$(echo "$response" | sed '$d')

        if [ "$http_code" -lt 200 ] || [ "$http_code" -ge 300 ]; then
            echo "Failed to create PR (HTTP $http_code):" >&2
            echo "$json" >&2
            exit 1
        fi
        echo "$json" | jq -r '.html_url'
        ;;
    comments)
        pr_number="${1:-}"
        if [ -z "$pr_number" ]; then
            echo "Usage: gitea-pr comments PR_NUMBER" >&2
            exit 1
        fi

        echo "=== Issue comments ==="
        response=$(curl -sS -w '\n%{http_code}' "${GITEA_API}/repos/${owner}/${repo}/issues/${pr_number}/comments" \
            -H "Authorization: token ${GITEA_TOKEN}")
        http_code=$(echo "$response" | tail -1)
        json=$(echo "$response" | sed '$d')
        if [ "$http_code" -lt 200 ] || [ "$http_code" -ge 300 ]; then
            echo "Failed to fetch issue comments (HTTP $http_code):" >&2
            echo "$json" >&2
            exit 1
        fi
        echo "$json" | jq -r '.[] | "[\(.user.login) @ \(.created_at)]\n\(.body)\n"'

        echo "=== Reviews ==="
        response=$(curl -sS -w '\n%{http_code}' "${GITEA_API}/repos/${owner}/${repo}/pulls/${pr_number}/reviews" \
            -H "Authorization: token ${GITEA_TOKEN}")
        http_code=$(echo "$response" | tail -1)
        reviews_json=$(echo "$response" | sed '$d')
        if [ "$http_code" -lt 200 ] || [ "$http_code" -ge 300 ]; then
            echo "Failed to fetch reviews (HTTP $http_code):" >&2
            echo "$reviews_json" >&2
            exit 1
        fi
        echo "$reviews_json" | jq -r '.[] | select(.body != "") | "[\(.user.login) @ \(.submitted_at) — \(.state)]\n\(.body)\n"'

        echo "=== Inline review comments ==="
        review_ids=$(echo "$reviews_json" | jq -r '.[] | select(.comments_count > 0) | .id')
        for review_id in $review_ids; do
            response=$(curl -sS -w '\n%{http_code}' \
                "${GITEA_API}/repos/${owner}/${repo}/pulls/${pr_number}/reviews/${review_id}/comments" \
                -H "Authorization: token ${GITEA_TOKEN}")
            http_code=$(echo "$response" | tail -1)
            json=$(echo "$response" | sed '$d')
            if [ "$http_code" -lt 200 ] || [ "$http_code" -ge 300 ]; then
                echo "Failed to fetch comments for review ${review_id} (HTTP $http_code):" >&2
                echo "$json" >&2
                exit 1
            fi
            echo "$json" | jq -r '.[] | "[\(.user.login) @ \(.path):\(.line // "?")]\n\(.body)\n"'
        done
        ;;
    merge)
        pr_number="${1:-}"
        if [ -z "$pr_number" ]; then
            echo "Usage: gitea-pr merge PR_NUMBER" >&2
            exit 1
        fi

        response=$(curl -sS -w '\n%{http_code}' -X POST "${GITEA_API}/repos/${owner}/${repo}/pulls/${pr_number}/merge" \
            -H "Authorization: token ${GITEA_TOKEN}" \
            -H "Content-Type: application/json" \
            -d '{"Do": "merge"}')
        http_code=$(echo "$response" | tail -1)
        json=$(echo "$response" | sed '$d')

        if [ "$http_code" -lt 200 ] || [ "$http_code" -ge 300 ]; then
            echo "Failed to merge PR #${pr_number} (HTTP $http_code):" >&2
            echo "$json" >&2
            exit 1
        fi
        echo "Merged PR #${pr_number}"
        ;;
esac
