#!/bin/sh
# Launched by /usr/lib/systemd/user/zia-bridge.service.
# Starts the OpenCode sdk-bridge (Node) with the bundled OpenCode CLI on PATH
# and a stable XDG_STATE_HOME, so logs land where the UI expects them.

set -e

DEFAULT_ENV="/usr/share/zia-forsuryaos/defaults/environment"
SYSTEM_ENV="/etc/zia-forsuryaos/environment"
USER_ENV="${XDG_CONFIG_HOME:-$HOME/.config}/zia-forsuryaos/environment"

BRIDGE_DIR="/usr/libexec/zia-forsuryaos/sdk-bridge"
BRIDGE_SCRIPT="$BRIDGE_DIR/bridge.js"
BUNDLED_BIN="/usr/libexec/zia-forsuryaos/bin"

load_env_file() {
  if [ -f "$1" ]; then
    set -a
    # shellcheck disable=SC1090
    . "$1"
    set +a
  fi
}

load_env_file "$DEFAULT_ENV"
load_env_file "$SYSTEM_ENV"
load_env_file "$USER_ENV"

# Pin a stable state dir so the bridge logs land at the same path the QML UI
# resolves via OpenCodeSDK::eventLogDir(). Only set if the unit didn't already.
: "${XDG_STATE_HOME:=$HOME/.local/state}"
export XDG_STATE_HOME

# OpenCode project root: small dedicated workspace (never $HOME — avoids multi-GB snapshots).
# SuryaOS default user home is /home/zos; fall back to $HOME/.zia-workspace on other installs.
if [ -z "${OPENCODE_PROJECT_ROOT:-}" ]; then
  if [ -d /home/zos ] || [ "$HOME" = /home/zos ]; then
    OPENCODE_PROJECT_ROOT=/home/zos/.zia-workspace
  else
    OPENCODE_PROJECT_ROOT="${ZIA_WORKSPACE_ROOT:-$HOME/.zia-workspace}"
  fi
fi
export OPENCODE_PROJECT_ROOT
mkdir -p "$OPENCODE_PROJECT_ROOT" 2>/dev/null || true

WORKSPACE_OPENCODE="$OPENCODE_PROJECT_ROOT/.opencode"
SYSTEM_OPENCODE="/usr/share/zia-forsuryaos/opencode-project/.opencode"
LEGACY_OPENCODE="$HOME/.opencode"

# One-time migration from the old $HOME/.opencode layout.
if [ ! -d "$WORKSPACE_OPENCODE" ] && [ -d "$LEGACY_OPENCODE" ]; then
  cp -a "$LEGACY_OPENCODE" "$WORKSPACE_OPENCODE"
  echo "zia-bridge-launcher: migrated $LEGACY_OPENCODE -> $WORKSPACE_OPENCODE" >&2
fi

if [ ! -d "$WORKSPACE_OPENCODE" ] && [ -d "$SYSTEM_OPENCODE" ]; then
  cp -a "$SYSTEM_OPENCODE" "$WORKSPACE_OPENCODE"
  echo "zia-bridge-launcher: seeded $WORKSPACE_OPENCODE from system bundle" >&2
elif [ -d "$SYSTEM_OPENCODE" ] && [ -d "$WORKSPACE_OPENCODE" ]; then
  # On package upgrade merge newer bundle configs into the workspace copy.
  for src in "$SYSTEM_OPENCODE"/*.jsonc "$SYSTEM_OPENCODE"/*.json; do
    [ -f "$src" ] || continue
    fname="$(basename "$src")"
    dest="$WORKSPACE_OPENCODE/$fname"
    if [ ! -f "$dest" ] || [ "$src" -nt "$dest" ]; then
      cp -a "$src" "$dest"
      echo "zia-bridge-launcher: updated $dest from system bundle" >&2
    fi
  done
  if [ -d "$SYSTEM_OPENCODE/agent" ]; then
    mkdir -p "$WORKSPACE_OPENCODE/agent" 2>/dev/null || true
    for src in "$SYSTEM_OPENCODE/agent"/*.md; do
      [ -f "$src" ] || continue
      fname="$(basename "$src")"
      dest="$WORKSPACE_OPENCODE/agent/$fname"
      if [ ! -f "$dest" ] || [ "$src" -nt "$dest" ]; then
        cp -a "$src" "$dest"
        echo "zia-bridge-launcher: updated $dest from system bundle" >&2
      fi
    done
  fi
fi

# KDE tools require @opencode-ai/plugin under workspace .opencode/node_modules.
PLUGIN_PKG="$WORKSPACE_OPENCODE/node_modules/@opencode-ai/plugin"
if [ ! -e "$PLUGIN_PKG" ]; then
  mkdir -p "$WORKSPACE_OPENCODE/node_modules/@opencode-ai" 2>/dev/null || true
  if [ -d "$SYSTEM_OPENCODE/node_modules/@opencode-ai/plugin" ]; then
    ln -sfn "$SYSTEM_OPENCODE/node_modules/@opencode-ai/plugin" "$PLUGIN_PKG" 2>/dev/null || true
    [ -d "$SYSTEM_OPENCODE/node_modules/@opencode-ai/sdk" ] && \
      ln -sfn "$SYSTEM_OPENCODE/node_modules/@opencode-ai/sdk" \
        "$WORKSPACE_OPENCODE/node_modules/@opencode-ai/sdk" 2>/dev/null || true
  elif [ -d "$LEGACY_OPENCODE/node_modules/@opencode-ai/plugin" ]; then
    ln -sfn "$LEGACY_OPENCODE/node_modules/@opencode-ai/plugin" "$PLUGIN_PKG" 2>/dev/null || true
    [ -d "$LEGACY_OPENCODE/node_modules/@opencode-ai/sdk" ] && \
      ln -sfn "$LEGACY_OPENCODE/node_modules/@opencode-ai/sdk" \
        "$WORKSPACE_OPENCODE/node_modules/@opencode-ai/sdk" 2>/dev/null || true
  elif [ -d "$BRIDGE_DIR/node_modules/@opencode-ai/plugin" ]; then
    ln -sfn "$BRIDGE_DIR/node_modules/@opencode-ai/plugin" "$PLUGIN_PKG" 2>/dev/null || true
  fi
  if [ -e "$PLUGIN_PKG" ]; then
    echo "zia-bridge-launcher: linked @opencode-ai/plugin into workspace" >&2
  else
    echo "zia-bridge-launcher: WARN missing @opencode-ai/plugin in $WORKSPACE_OPENCODE (run npm install in .opencode)" >&2
  fi
fi

mkdir -p "$XDG_STATE_HOME/opencode-bridge/logs" 2>/dev/null || true

# Bundled OpenCode CLI on PATH so the SDK can spawn it without needing the
# curl|bash installer on the user's machine.
if [ -d "$BUNDLED_BIN" ]; then
  PATH="$BUNDLED_BIN:$PATH"
  export PATH
fi

if [ ! -f "$BRIDGE_SCRIPT" ]; then
  echo "zia-bridge-launcher: bridge script not found at $BRIDGE_SCRIPT" >&2
  exit 1
fi

# Resolve a node binary; prefer the system one (Depends: nodejs in control).
NODE_BIN="${NODE_BIN:-$(command -v node || true)}"
if [ -z "$NODE_BIN" ]; then
  echo "zia-bridge-launcher: node not found on PATH (install nodejs)" >&2
  exit 127
fi

# Reap stale bridge AND opencode-serve processes that may still be holding
# ports from a previous service instance.  Without this cleanup the new bridge
# gets EADDRINUSE and the OmniBar shows "Connection refused".
BRIDGE_PORT="${OPENCODE_BRIDGE_PORT:-8765}"
SDK_PORT="${OPENCODE_SDK_PORT:-4096}"
SELF_PID="$$"

reap_port() {
  port="$1"
  match_pattern="$2"
  pids=""
  if command -v fuser >/dev/null 2>&1; then
    pids="$(fuser -n tcp "$port" 2>/dev/null | tr -s ' \t' '\n' | sed '/^$/d' | sort -u)"
  fi
  if [ -z "$pids" ] && command -v ss >/dev/null 2>&1; then
    pids="$(ss -ltnpH 2>/dev/null | awk -v p=":$port" '$4 ~ p"$" {print $0}' \
      | grep -oE 'pid=[0-9]+' | cut -d= -f2 | sort -u)"
  fi
  [ -z "$pids" ] && return 0
  for pid in $pids; do
    [ "$pid" = "$SELF_PID" ] && continue
    [ "$pid" -gt 0 ] 2>/dev/null || continue
    cmdline=""
    [ -r "/proc/$pid/cmdline" ] && cmdline="$(tr '\0' ' ' < "/proc/$pid/cmdline" 2>/dev/null)"
    case "$cmdline" in
      *$match_pattern*) ;;
      *) continue ;;
    esac
    echo "zia-bridge-launcher: terminating stale pid=$pid (held :$port)" >&2
    kill -TERM "$pid" 2>/dev/null || true
  done
  i=0
  while [ "$i" -lt 30 ]; do
    still=""
    if command -v fuser >/dev/null 2>&1; then
      still="$(fuser -n tcp "$port" 2>/dev/null)"
    fi
    [ -z "$still" ] && break
    sleep 0.1
    i=$((i + 1))
  done
  for pid in $pids; do
    [ "$pid" = "$SELF_PID" ] && continue
    [ -d "/proc/$pid" ] || continue
    echo "zia-bridge-launcher: SIGKILL stale pid=$pid (still on :$port)" >&2
    kill -KILL "$pid" 2>/dev/null || true
  done
}

reap_port "$BRIDGE_PORT" "sdk-bridge/bridge.js"
reap_port "$BRIDGE_PORT" "/bridge.js"
reap_port "$BRIDGE_PORT" "zia-bridge-launcher"
reap_port "$BRIDGE_PORT" "opencode-kde-sdk-bridge"
# Dev-tree starts (e.g. Opencode_Frontier/src/services/sdk-bridge/bridge.js)
reap_port "$BRIDGE_PORT" "Opencode_Frontier"
reap_port "$SDK_PORT" "opencode"

cd "$BRIDGE_DIR" || exit 1
exec "$NODE_BIN" "$BRIDGE_SCRIPT"
