#!/usr/bin/env bash
set -uo pipefail

WORKSPACE="" PROMPT="" TASK_SLUG="" MODEL="" PROFILE="" TIMEOUT=360 SESSION_ID=""
MODE="dispatch"
while [[ $# -gt 0 ]]; do
  case "$1" in
    --workspace) [[ $# -lt 2 ]] && { echo '{"ok":false,"detail":"--workspace requires a value"}' >&2; exit 2; }; WORKSPACE="${2:-}"; shift 2;;
    --trust)     [[ $# -lt 2 ]] && { echo '{"ok":false,"detail":"--trust requires a value"}' >&2; exit 2; }; PROMPT="${2:-}";    shift 2;;
    --task-slug) [[ $# -lt 2 ]] && { echo '{"ok":false,"detail":"--task-slug requires a value"}' >&2; exit 2; }; TASK_SLUG="${2:-}"; shift 2;;
    --model)     [[ $# -lt 2 ]] && { echo '{"ok":false,"detail":"--model requires a value"}' >&2; exit 2; }; MODEL="${2:-}";     shift 2;;
    --timeout)   [[ $# -lt 2 ]] && { echo '{"ok":false,"detail":"--timeout requires a value"}' >&2; exit 2; }; TIMEOUT="${2:-}";   shift 2;;
    --profile) [[ $# -lt 2 ]] && { echo '{"ok":false,"detail":"--profile requires a value"}' >&2; exit 2; }; PROFILE="${2:-}"; shift 2;;
    --session-id) [[ $# -lt 2 ]] && { echo '{"ok":false,"detail":"--session-id requires a value"}' >&2; exit 2; }; SESSION_ID="${2:-}"; shift 2;;
    --health) MODE="health"; shift;;
    --list-models) MODE="list-models"; shift;;
    --interactive) MODE="interactive"; shift;;
    *) shift;;
  esac
done
[[ -n "$PROFILE" ]] && echo "notice: --profile=$PROFILE ignored — opencode.sh has no account routing" >&2

SKILL_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/.."
source "$SKILL_DIR/wrappers/lib/finalize.sh"
_OPENCODE_BIN="${_OPENCODE_ENGINE_BIN:-opencode}"

opencode_available() {
  command -v "$_OPENCODE_BIN" >/dev/null 2>&1
}

case "$MODE" in
  health)
    opencode_available || { echo '{"ok":false,"detail":"opencode binary not found"}' >&2; exit 3; }
    if ! models_out="$(timeout 10 "$_OPENCODE_BIN" models 2>/dev/null)"; then
      echo '{"ok":false,"detail":"opencode models probe failed — provider unreachable"}' >&2
      exit 3
    fi
    MODELS_OUT="$models_out" python3 - <<'PY'
import json
import os

models = os.environ.get("MODELS_OUT", "").strip()
print(json.dumps({"ok": True, "reachable": bool(models)}, separators=(",", ":")))
PY
    exit 0
    ;;
  list-models)
    opencode_available || { echo '{"ok":false,"detail":"opencode binary not found"}' >&2; exit 3; }
    "$_OPENCODE_BIN" models
    exit $?
    ;;
  interactive)
    echo '{"ok":false,"detail":"--interactive is not supported by wrappers/opencode.sh; run opencode directly in the workspace"}' >&2
    exit 2
    ;;
esac

TASK_SLUG="${TASK_SLUG//[^a-zA-Z0-9_-]/}"
RUN_ID="$(date +%Y-%m-%d-%H-%M-%S)-$$"

[[ -n "$WORKSPACE" && -d "$WORKSPACE" ]] || { echo '{"ok":false,"detail":"--workspace missing or not a dir"}' >&2; exit 2; }
[[ -n "$PROMPT" ]]    || { echo '{"ok":false,"detail":"--trust (prompt) required"}' >&2; exit 2; }
[[ -n "$TASK_SLUG" ]] || { echo '{"ok":false,"detail":"--task-slug required (log + retry hygiene)"}' >&2; exit 2; }
[[ -n "$MODEL" ]]     || { echo '{"ok":false,"detail":"--model required (no silent default)"}' >&2; exit 2; }

opencode_available || { echo '{"ok":false,"detail":"opencode binary not found"}' >&2; exit 3; }

LOG_DIR="${HARNESS_LOG_DIR:-$HOME/Projects/mega-plan-harness/tmp/logs}"
# A read-only reviewer workspace leaves the shared log dir unwritable; tee would then
# fail on every line it emits.
if ! mkdir -p "$LOG_DIR" 2>/dev/null || [[ ! -w "$LOG_DIR" ]]; then
  LOG_DIR="${TMPDIR:-/tmp}/harness-opencode-logs"
  mkdir -p "$LOG_DIR" || { echo '{"ok":false,"detail":"no writable log dir"}' >&2; exit 3; }
fi
LOG="$LOG_DIR/$RUN_ID-$TASK_SLUG.log"
RAW_OUTPUT_FILE="$LOG_DIR/$RUN_ID-$TASK_SLUG.raw"
TRANSCRIPT_PATH="${HARNESS_TRANSCRIPT_PATH:-}"
if [[ -n "$TRANSCRIPT_PATH" ]]; then
  mkdir -p "$(dirname "$TRANSCRIPT_PATH")" || { echo '{"ok":false,"detail":"transcript dir create failed"}' >&2; exit 3; }
fi

stream_output() {
  if [[ -n "$TRANSCRIPT_PATH" ]]; then
    tee -a "$LOG" "$RAW_OUTPUT_FILE" "$TRANSCRIPT_PATH"
  else
    tee -a "$LOG" "$RAW_OUTPUT_FILE"
  fi
}

emit_event_line() {
  local line="$1"
  if [[ -n "$TRANSCRIPT_PATH" ]]; then
    printf '%s\n' "$line" | tee -a "$LOG" "$TRANSCRIPT_PATH"
  else
    printf '%s\n' "$line" | tee -a "$LOG"
  fi
}

# --format json nests the reply inside an event's escaped text field, where the engine's
# bare-top-level-JSON-line scavenger cannot reach it. Default format keeps it extractable.
OPENCODE_RUN=(run --model "$MODEL" --dangerously-skip-permissions --dir "$WORKSPACE")
[[ -n "$SESSION_ID" ]] && OPENCODE_RUN+=(--session "$SESSION_ID")
OPENCODE_RUN+=("$PROMPT")
OPENCODE_ARGS=(timeout -k 5 "$TIMEOUT" "$_OPENCODE_BIN" "${OPENCODE_RUN[@]}")
{
  echo "=== TOOL: opencode (${MODEL}) ==="
  echo "=== CMD: $(printf '%q ' "${OPENCODE_ARGS[@]}") ==="
  echo "=== workspace: $WORKSPACE  timeout: ${TIMEOUT}s  log: $LOG ==="
  [[ -n "$SESSION_ID" ]] && echo "=== session_id: $SESSION_ID ==="
} | tee "$LOG"

cd "$WORKSPACE" || { echo '{"ok":false,"detail":"cd workspace failed"}' >&2; exit 2; }
"${OPENCODE_ARGS[@]}" < /dev/null 2>&1 | stream_output
RC="${PIPESTATUS[0]}"
echo "=== opencode exit=$RC ===" | tee -a "$LOG"
finalize_terminal "$RC" 'opencode' "$SESSION_ID" '' "$MODEL"
