#!/usr/bin/env bash
# cortex-graph-build — build graph through API by default.

set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# shellcheck source=./_cortex_api.sh
source "${SCRIPT_DIR}/_cortex_api.sh"
# shellcheck source=./_cortex_lib.sh
source "${SCRIPT_DIR}/_cortex_lib.sh"

usage() {
    cat <<'EOF'
Usage: cortex-graph-build [--repo PATH] [--full] [--no-embed] [--local-worker]
                          [--import-existing]
                          [--sync] [--no-wait|--wait] [--wait-timeout SECONDS]
                          [--poll-interval SECONDS] [--job JOB_ID]
EOF
}

REPO="$(pwd)"
FULL=false
EMBED=true
LOCAL_WORKER=0
IMPORT_EXISTING=false
ASYNC_JOB=true
SYNC=false
WAIT=true
WAIT_TIMEOUT="${CORTEX_GRAPH_BUILD_WAIT_TIMEOUT:-900}"
POLL_INTERVAL="${CORTEX_GRAPH_BUILD_POLL_INTERVAL:-2}"
JOB_ID=""
MODE="build"

while [ "$#" -gt 0 ]; do
    case "$1" in
        --repo) REPO="$2"; shift 2 ;;
        --full) FULL=true; shift ;;
        --no-embed) EMBED=false; shift ;;
        --local-worker) LOCAL_WORKER=1; shift ;;
        --import-existing) IMPORT_EXISTING=true; shift ;;
        --sync) ASYNC_JOB=false; SYNC=true; WAIT=false; shift ;;
        --async) ASYNC_JOB=true; SYNC=false; shift ;;
        --no-wait) WAIT=false; shift ;;
        --wait) WAIT=true; shift ;;
        --wait-timeout) WAIT_TIMEOUT="$2"; shift 2 ;;
        --poll-interval) POLL_INTERVAL="$2"; shift 2 ;;
        --job|--status) MODE="job"; JOB_ID="$2"; shift 2 ;;
        --help|-h) usage; exit 0 ;;
        *) echo "ERROR: unknown option: $1" >&2; usage >&2; exit 2 ;;
    esac
done

if [ "${MODE}" = "job" ]; then
    if [ -z "${JOB_ID}" ]; then
        echo "ERROR: --job requires a job id" >&2
        exit 2
    fi
    cortex_api_call_json GET "/graph/build/jobs/${JOB_ID%%:*}"
    exit 0
fi

if [ "${LOCAL_WORKER}" -eq 1 ]; then
    if [ "${IMPORT_EXISTING}" = "true" ]; then
        echo "ERROR: --import-existing cannot be combined with --local-worker" >&2
        exit 2
    fi
    cortex_prepare_code_graph_env "${REPO}"
    export CORTEX_GRAPH_BUILD_REPO="${REPO}" CORTEX_GRAPH_BUILD_FULL="${FULL}"
    exec uv tool run --from better-code-review-graph python - <<'PYEOF'
import json
import os

from better_code_review_graph.tools import build_or_update_graph

repo = os.environ["CORTEX_GRAPH_BUILD_REPO"]
full = os.environ.get("CORTEX_GRAPH_BUILD_FULL", "false").lower() == "true"
result = build_or_update_graph(full_rebuild=full, repo_root=repo)
if isinstance(result, str):
    try:
        result = json.loads(result)
    except Exception:
        pass
print(json.dumps(result, indent=2, default=str) if not isinstance(result, str) else result)
PYEOF
fi

payload="$(python3 - "${REPO}" "${FULL}" "${EMBED}" "${ASYNC_JOB}" "${SYNC}" "${IMPORT_EXISTING}" <<'PYEOF'
import json, sys
print(json.dumps({
    "repo": sys.argv[1],
    "full": sys.argv[2].lower() == "true",
    "embed": sys.argv[3].lower() == "true",
    "async_job": sys.argv[4].lower() == "true",
    "sync": sys.argv[5].lower() == "true",
    "import_existing": sys.argv[6].lower() == "true",
}))
PYEOF
)"

response="$(cortex_api_call_json POST "/graph/build" "${payload}")"

job_id="$(python3 - "${response}" <<'PYEOF'
import json, sys
try:
    data = json.loads(sys.argv[1])
except Exception:
    raise SystemExit(0)
print(data.get("job_id") or "")
PYEOF
)"

if [ -z "${job_id}" ] || [ "${WAIT}" != "true" ]; then
    printf '%s\n' "${response}"
    exit 0
fi

printf '%s\n' "${response}" >&2
deadline=$(( $(date +%s) + WAIT_TIMEOUT ))
last_status=""
while true; do
    status_payload="$(cortex_api_call_json GET "/graph/build/jobs/${job_id}")"
    status_line="$(python3 - "${status_payload}" <<'PYEOF'
import json, sys
data = json.loads(sys.argv[1])
print("status={status} repo={repo}".format(
    status=data.get("status"),
    repo=data.get("repo", ""),
))
PYEOF
)"
    if [ "${status_line}" != "${last_status}" ]; then
        printf '%s\n' "${status_line}" >&2
        last_status="${status_line}"
    fi
    job_status="${status_line#status=}"
    job_status="${job_status%% *}"
    case "${job_status}" in
        completed)
            printf '%s\n' "${status_payload}"
            exit 0
            ;;
        failed)
            printf '%s\n' "${status_payload}"
            exit 1
            ;;
    esac
    if [ "$(date +%s)" -ge "${deadline}" ]; then
        printf 'ERROR: graph build job %s still running after %ss; inspect with cortex-graph-build --job %s\n' "${job_id}" "${WAIT_TIMEOUT}" "${job_id}" >&2
        printf '%s\n' "${status_payload}"
        exit 124
    fi
    sleep "${POLL_INTERVAL}"
done
