#!/bin/bash
# pr-metadata.sh - Get PR metadata as JSON on GitHub or Gitea
# Usage: pr-metadata.sh -n <pr_number> [-o <output_file>]

set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# shellcheck source=packages/mosaic/framework/tools/git/detect-platform.sh
source "$SCRIPT_DIR/detect-platform.sh"

# Parse arguments
PR_NUMBER=""
OUTPUT_FILE=""

while [[ $# -gt 0 ]]; do
    case $1 in
        -n|--number)
            PR_NUMBER="$2"
            shift 2
            ;;
        -o|--output)
            OUTPUT_FILE="$2"
            shift 2
            ;;
        -h|--help)
            echo "Usage: pr-metadata.sh -n <pr_number> [-o <output_file>]"
            echo ""
            echo "Options:"
            echo "  -n, --number   PR number (required)"
            echo "  -o, --output   Output file (optional, prints to stdout if omitted)"
            echo "  -h, --help     Show this help"
            exit 0
            ;;
        *)
            echo "Unknown option: $1" >&2
            exit 1
            ;;
    esac
done

if [[ -z "$PR_NUMBER" ]]; then
    echo "Error: PR number is required (-n)" >&2
    exit 1
fi

write_metadata() {
    local metadata="$1"
    if [[ -n "$OUTPUT_FILE" ]]; then
        printf '%s\n' "$metadata" > "$OUTPUT_FILE"
    else
        printf '%s\n' "$metadata"
    fi
}

curl_gitea_pull() {
    local api_url="$1"
    local token basic_auth raw_code body_file http_code
    body_file=$(mktemp)

    # shellcheck disable=SC2329 # Invoked by the RETURN trap below.
    cleanup_gitea_pull_body() {
        local status=$?
        rm -f -- "$body_file"
        trap - RETURN
        return "$status"
    }
    trap cleanup_gitea_pull_body RETURN

    token=$(get_gitea_token "$HOST" || true)
    if [[ -n "$token" ]]; then
        raw_code=$(curl -sS -w '%{http_code}' -o "$body_file" -H "User-Agent: curl/8" -H "Authorization: token $token" "$api_url" || true)
        if [[ "$raw_code" =~ ^2 ]]; then
            cat "$body_file" || return $?
            return 0
        fi
        http_code="$raw_code"
    fi

    basic_auth=$(get_gitea_basic_auth "$HOST" || true)
    if [[ -n "$basic_auth" ]]; then
        raw_code=$(curl -sS -w '%{http_code}' -o "$body_file" -u "$basic_auth" -H "User-Agent: curl/8" "$api_url" || true)
        if [[ "$raw_code" =~ ^2 ]]; then
            cat "$body_file" || return $?
            return 0
        fi
        http_code="$raw_code"
    fi

    if [[ -z "${http_code:-}" ]]; then
        raw_code=$(curl -sS -w '%{http_code}' -o "$body_file" -H "User-Agent: curl/8" "$api_url" || true)
        http_code="$raw_code"
    fi

    python3 - "$http_code" "$body_file" <<'PY' >&2
import json
import sys

code, path = sys.argv[1], sys.argv[2]
try:
    data = json.load(open(path, encoding="utf-8"))
    message = data.get("message") or data.get("error") or "unknown API error"
except Exception:
    message = open(path, encoding="utf-8", errors="replace").read()[:200] or "empty response"
print(f"Error: Gitea pull request API request failed with HTTP {code}: {message}")
PY
    return 1
}

detect_platform > /dev/null

if [[ "$PLATFORM" == "github" ]]; then
    METADATA=$(gh pr view "$PR_NUMBER" --json number,title,body,state,author,headRefName,baseRefName,files,labels,assignees,milestone,createdAt,updatedAt,url,isDraft)
    write_metadata "$METADATA"
elif [[ "$PLATFORM" == "gitea" ]]; then
    OWNER=$(get_repo_owner)
    REPO=$(get_repo_name)
    HOST=$(get_remote_host) || {
        echo "Error: Cannot determine host from origin remote URL" >&2
        exit 1
    }

    API_URL="https://${HOST}/api/v1/repos/${OWNER}/${REPO}/pulls/${PR_NUMBER}"
    if [[ -n "${MOSAIC_GITEA_PR_METADATA_RAW_FILE:-}" ]]; then
        RAW=$(cat "$MOSAIC_GITEA_PR_METADATA_RAW_FILE")
    else
        RAW=$(curl_gitea_pull "$API_URL")
    fi

    # Normalize Gitea response to match GitHub's expected metadata schema.
    METADATA=$(printf '%s' "$RAW" | python3 -c "
import json
import sys

def first_non_empty(*values):
    for value in values:
        if value is None:
            continue
        if isinstance(value, str):
            value = value.strip()
        if value:
            return value
    return ''

def nested(data, *keys):
    current = data
    for key in keys:
        if not isinstance(current, dict):
            return None
        current = current.get(key)
    return current

try:
    data = json.load(sys.stdin)
except json.JSONDecodeError as exc:
    print(f'Error: Gitea API returned non-JSON response: {exc}', file=sys.stderr)
    sys.exit(1)

if not isinstance(data, dict):
    print('Error: Gitea API returned an unexpected non-object response', file=sys.stderr)
    sys.exit(1)

if data.get('message') and not data.get('number'):
    print(f\"Error: Gitea API error: {data.get('message')}\", file=sys.stderr)
    sys.exit(1)

head_ref = first_non_empty(
    nested(data, 'head', 'ref'),
    nested(data, 'head', 'name'),
    nested(data, 'head', 'branch'),
    data.get('head_branch'),
    data.get('head_ref'),
    nested(data, 'head', 'label'),
    data.get('head_label'),
)
if isinstance(head_ref, str) and head_ref.startswith('refs/pull/'):
    head_ref = first_non_empty(
        nested(data, 'head', 'label'),
        data.get('head_label'),
        nested(data, 'head', 'name'),
        nested(data, 'head', 'branch'),
        data.get('head_branch'),
        data.get('head_ref'),
        head_ref,
    )
base_ref = first_non_empty(
    nested(data, 'base', 'ref'),
    nested(data, 'base', 'name'),
    nested(data, 'base', 'branch'),
    data.get('base_branch'),
    data.get('base_ref'),
    data.get('base_label'),
)

if not head_ref or not base_ref:
    available = ', '.join(sorted(data.keys()))
    print(
        'Error: Unable to resolve non-empty Gitea PR head/base refs '
        f'(headRefName={head_ref!r}, baseRefName={base_ref!r}; keys={available})',
        file=sys.stderr,
    )
    sys.exit(1)

normalized = {
    'number': data.get('number'),
    'title': data.get('title'),
    'body': data.get('body', ''),
    'state': data.get('state'),
    'author': nested(data, 'user', 'login') or '',
    'headRefName': head_ref,
    'baseRefName': base_ref,
    'labels': [l.get('name', '') for l in data.get('labels', []) if isinstance(l, dict)],
    'assignees': [a.get('login', '') for a in data.get('assignees', []) if isinstance(a, dict)],
    'milestone': nested(data, 'milestone', 'title') or '',
    'createdAt': data.get('created_at', ''),
    'updatedAt': data.get('updated_at', ''),
    'url': data.get('html_url', ''),
    'isDraft': data.get('draft', False),
    'mergeable': data.get('mergeable'),
    'diffUrl': data.get('diff_url', ''),
}
json.dump(normalized, sys.stdout, indent=2)
")

    write_metadata "$METADATA"
else
    echo "Error: Unknown platform" >&2
    exit 1
fi
