#!/usr/bin/env sh
set -eu

repo_url="${HOUSEHOLD_REPO_URL:-https://github.com/Wouterbeets/household.git}"
relay_url="${HOUSEHOLD_RELAY_URL:-https://household.beets.cloud}"
prefix="${HOUSEHOLD_PREFIX:-$HOME/.local}"
config_dir="${XDG_CONFIG_HOME:-$HOME/.config}/Household"
state_dir="${XDG_STATE_HOME:-$HOME/.local/state}/household"
cache_dir="${XDG_CACHE_HOME:-$HOME/.cache}/Household"
src_dir="${HOUSEHOLD_SRC_DIR:-$state_dir/src}"
bin_dir="$prefix/bin"
bin_path="$bin_dir/household"
desktop_path="$prefix/share/applications/household.desktop"
icon_path="$prefix/share/icons/hicolor/512x512/apps/household.png"
config_path="$config_dir/desktop.json"

usage() {
  cat <<EOF
Household desktop installer

Usage: sh install-household-home.sh [--claim NAME] [--start] [--open]

Commands:
  --doctor          Check local prerequisites and current install status.

Environment:
  HOUSEHOLD_REPO_URL   Git repo to clone (default: $repo_url)
  HOUSEHOLD_RELAY_URL  Relay URL (default: $relay_url)
  HOUSEHOLD_PREFIX     Install prefix (default: $prefix)
  HOUSEHOLD_SRC_DIR    Source checkout (default: $src_dir)

The installed desktop app owns the local server. When the app is closed,
remote phone access is off and local secrets stay on this computer.
EOF
}

claim_name=""
dry_run=false
doctor=false
start_app=false
open_app=false
while [ "$#" -gt 0 ]; do
  case "$1" in
    --claim)
      claim_name="${2:-}"
      if [ -z "$claim_name" ]; then
        echo "--claim requires a household name" >&2
        exit 2
      fi
      shift 2
      ;;
    --start|--open)
      start_app=true
      open_app=true
      shift
      ;;
    --dry-run)
      dry_run=true
      shift
      ;;
    --doctor)
      doctor=true
      shift
      ;;
    -h|--help)
      usage
      exit 0
      ;;
    *)
      echo "unknown option: $1" >&2
      usage >&2
      exit 2
      ;;
  esac
done

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

need() {
  if ! have "$1"; then
    echo "missing required command: $1" >&2
    return 1
  fi
}

check_port() {
  port="$1"
  if have lsof; then
    lsof -nP -iTCP:"$port" -sTCP:LISTEN >/dev/null 2>&1
    return $?
  fi
  if have ss; then
    ss -ltn 2>/dev/null | grep -Eq "[.:]$port[[:space:]]"
    return $?
  fi
  return 2
}

json_escape() {
  printf '%s' "$1" | sed 's/\\/\\\\/g; s/"/\\"/g'
}

disable_old_services() {
  if ! have systemctl; then
    return 0
  fi
  for unit in household.service kanban.service; do
    systemctl --user disable --now "$unit" >/dev/null 2>&1 || true
  done
  systemctl --user daemon-reload >/dev/null 2>&1 || true
}

print_doctor() {
  echo "Household desktop installer doctor:"
  echo "  os: $(uname -s 2>/dev/null || echo unknown)"
  echo "  arch: $(uname -m 2>/dev/null || echo unknown)"
  for cmd in git go curl pkg-config update-desktop-database gtk-update-icon-cache; do
    if have "$cmd"; then
      echo "  $cmd: $(command -v "$cmd")"
    else
      echo "  $cmd: missing"
    fi
  done
  if have pkg-config; then
    if pkg-config --exists gtk+-3.0 gio-unix-2.0 webkit2gtk-4.1 libsoup-3.0; then
      echo "  desktop libraries: present"
    else
      echo "  desktop libraries: missing; on Ubuntu run: sudo apt install libgtk-3-dev libwebkit2gtk-4.1-dev"
    fi
  fi
  if check_port 33333; then
    echo "  port 33333: in use"
  else
    case "$?" in
      1) echo "  port 33333: free" ;;
      *) echo "  port 33333: unknown (install lsof or ss for checks)" ;;
    esac
  fi
  echo "  source: $src_dir"
  echo "  app: $bin_path"
  echo "  launcher: $desktop_path"
  echo "  config: $config_path"
  if have systemctl; then
    for unit in household.service kanban.service; do
      if systemctl --user is-active "$unit" >/dev/null 2>&1; then
        echo "  old $unit: active"
      elif systemctl --user status "$unit" >/dev/null 2>&1; then
        echo "  old $unit: installed but inactive"
      else
        echo "  old $unit: not installed"
      fi
    done
  fi
}

if [ "$doctor" = true ]; then
  print_doctor
  exit 0
fi

if [ "$dry_run" = true ]; then
  echo "Household desktop installer dry run:"
  echo "  repo: $repo_url"
  echo "  relay: $relay_url"
  echo "  source: $src_dir"
  echo "  app: $bin_path"
  echo "  launcher: $desktop_path"
  echo "  config: $config_path"
  echo "  claim: ${claim_name:-none}"
  echo "  open app: $open_app"
  exit 0
fi

need git
need go
need curl
need pkg-config
if ! pkg-config --exists gtk+-3.0 gio-unix-2.0 webkit2gtk-4.1 libsoup-3.0; then
  echo "missing desktop build libraries. On Ubuntu run:" >&2
  echo "  sudo apt install libgtk-3-dev libwebkit2gtk-4.1-dev" >&2
  exit 1
fi

mkdir -p "$bin_dir" "$config_dir" "$state_dir" "$cache_dir" "$(dirname "$desktop_path")" "$(dirname "$icon_path")"

if [ -d "$src_dir/.git" ]; then
  git -C "$src_dir" fetch --depth 1 origin main
  git -C "$src_dir" checkout -q main
  git -C "$src_dir" reset --hard -q origin/main
else
  rm -rf "$src_dir"
  git clone --depth 1 "$repo_url" "$src_dir"
fi

(cd "$src_dir" && go build -tags desktop,production,webkit2_41 -o "$bin_path" ./desktop)
install -m 0644 "$src_dir/desktop/assets/household.png" "$icon_path"

household_id=""
home_token=""
if [ -n "$claim_name" ]; then
  claim_json="$(curl -fsS -X POST "$relay_url/auth/claim-slot" \
    -H 'Accept: application/json' \
    --data-urlencode "household_name=$claim_name")"
  household_id="$(printf '%s' "$claim_json" | sed -n 's/.*"household_id"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p')"
  home_token="$(printf '%s' "$claim_json" | sed -n 's/.*"home_token"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p')"
  if [ -z "$household_id" ] || [ -z "$home_token" ]; then
    echo "claim response did not include household_id and home_token: $claim_json" >&2
    exit 1
  fi
fi

if [ ! -f "$config_path" ]; then
  umask 077
  cat >"$config_path" <<EOF
{
  "relay_url": "$(json_escape "$relay_url")",
  "relay_token": "$(json_escape "$home_token")",
  "db_path": "$(json_escape "$cache_dir/memory.db")",
  "memory_root": "$(json_escape "$cache_dir/memory")",
  "web_addr": "127.0.0.1:33333",
  "web_passphrase": "",
  "household_id": "$(json_escape "$household_id")",
  "device_key_path": "$(json_escape "$config_dir/device.key")",
  "paired_devices_path": "$(json_escape "$config_dir/paired-devices.json")",
  "ai_runtime_enabled": false,
  "ai_runtime_dir": "$(json_escape "$prefix/share/household-ai")",
  "ai_env_path": "$(json_escape "${XDG_CONFIG_HOME:-$HOME/.config}/household/household-ai.env")",
  "brain": "legacy",
  "push": false,
  "pull_before": false,
  "skip_heartbeat": true,
  "heartbeat_interval": "10m",
  "heartbeat_agent": false,
  "heartbeat_morning": false
}
EOF
elif [ -n "$household_id" ]; then
  echo "Household was claimed, but $config_path already exists; keep existing config or update it in the app." >&2
fi

cat >"$desktop_path" <<EOF
[Desktop Entry]
Type=Application
Name=Household
Comment=Household memory and planning
Exec=$bin_path
Icon=household
Terminal=false
Categories=Office;ProjectManagement;
StartupNotify=true
EOF

disable_old_services
update-desktop-database "$(dirname "$desktop_path")" >/dev/null 2>&1 || true
gtk-update-icon-cache -q "$prefix/share/icons/hicolor" >/dev/null 2>&1 || true

echo "Household desktop app installed:"
echo "  app: $bin_path"
echo "  launcher: $desktop_path"
echo "  config: $config_path"
echo "  old user services: disabled if present"
echo "  off: close Household"
echo "  on: open Household from the app launcher"

if [ "$start_app" = true ] || [ "$open_app" = true ]; then
  if have gtk-launch; then
    gtk-launch household >/dev/null 2>&1 || "$bin_path" >/dev/null 2>&1 &
  else
    "$bin_path" >/dev/null 2>&1 &
  fi
fi
