#!/usr/bin/with-contenv bashio
# -*- bash -*-
# shellcheck shell=bash
set -e

# Database things
DATABASE_HOST=$(bashio::config 'database_host')
DATABASE_NAME=$(bashio::config 'database_name')
DATABASE_PASS=$(bashio::config 'database_pass')
DATABASE_PORT=$(bashio::config 'database_port')
DATABASE_USER=$(bashio::config 'database_user')

# MQTT things
DISABLE_MQTT=$(bashio::config 'disable_mqtt')
MQTT_HOST=$(bashio::config 'mqtt_host')
MQTT_NAMESPACE=$(bashio::config 'mqtt_namespace')
MQTT_PASSWORD=$(bashio::config 'mqtt_pass')
MQTT_TLS_ACCEPT_INVALID_CERTS=$(bashio::config 'mqtt_tls_accept_invalid_certs')
MQTT_TLS=$(bashio::config 'mqtt_tls')
MQTT_USERNAME=$(bashio::config 'mqtt_user')

# Other things
IMPORT_DIR=$(bashio::config 'import_dir')
PORT=4000
TZ=$(bashio::config 'timezone')
DEFAULT_GEOFENCE=$(bashio::config 'default_geofence')

encryption_key=$(bashio::config 'encryption_key')
if bashio::config.is_empty 'encryption_key'; then
  encryption_key=$(openssl rand -hex 32)
  bashio::addon.option 'encryption_key' "$encryption_key"
fi
ENCRYPTION_KEY=$(bashio::config 'encryption_key')

ingress_entry=$(curl -X GET \
                     -H "Authorization: Bearer ${SUPERVISOR_TOKEN}" \
                     -H "Content-Type: application/json" \
                     -s http://supervisor/addons/self/info | \
                     jq -r '.data.ingress_entry')

export URL_PATH=$ingress_entry

export DATABASE_HOST DATABASE_NAME DATABASE_PASS DATABASE_PORT DATABASE_USER \
  DISABLE_MQTT MQTT_HOST MQTT_NAMESPACE MQTT_PASSWORD MQTT_TLS_ACCEPT_INVALID_CERTS \
  MQTT_TLS MQTT_USERNAME IMPORT_DIR PORT TZ DEFAULT_GEOFENCE ENCRYPTION_KEY URL_PATH

# These are optional and applied last so we can override those set above if needed.
for env_var in $(bashio::config 'env_vars|keys'); do
    name=$(bashio::config "env_vars[${env_var}].name")
    value=$(bashio::config "env_vars[${env_var}].value")
    bashio::log.debug "Setting Env Variable ${name} to ${value}"
    export "${name}=${value}"
done

# Wait for PostgreSQL to be ready before continuing. The add-on can start
# before the database is accepting connections (e.g. on a Home Assistant reboot
# when both add-ons start together, or under load in CI), so retry instead of
# failing immediately - TeslaMate has no built-in retry for this pre-check and
# the s6 finish script would otherwise halt the whole add-on.
bashio::log.info "Waiting for PostgreSQL at '$DATABASE_HOST:$DATABASE_PORT'..."
pg_wait_attempt=0
pg_wait_max=30
until pg_isready -h "$DATABASE_HOST" -p "$DATABASE_PORT" > /dev/null 2>&1; do
  pg_wait_attempt=$((pg_wait_attempt + 1))
  if [[ "$pg_wait_attempt" -ge "$pg_wait_max" ]]; then
    bashio::log.error "PostgreSQL at '$DATABASE_HOST' is not ready or unreachable after $((pg_wait_max * 2))s"
    exit 1
  fi
  bashio::log.info "PostgreSQL not ready yet, retrying in 2s (${pg_wait_attempt}/${pg_wait_max})..."
  sleep 2
done
bashio::log.info "PostgreSQL is ready"

# Create the PostgreSQL database if it doesn't exist
bashio::log.info "Checking for database '$DATABASE_NAME' on $DATABASE_HOST"
# Check the version of PostgreSQL database is v16.7 or later or v17.3 or later
pg_version=$(PGPASSWORD="$DATABASE_PASS" psql -h "$DATABASE_HOST" -p "$DATABASE_PORT" -U "$DATABASE_USER" postgres -Atqc "SELECT regexp_replace(version(), 'PostgreSQL ([^ ]+) .*', '\\1') AS version")
major_version=$(echo "$pg_version" | cut -d '.' -f 1)
minor_version=$(echo "$pg_version" | cut -d '.' -f 2)
compat=true
case "$major_version" in
  16)
    [[ "$minor_version" -lt 7 ]] && compat=false
    ;;
  17)
    [[ "$minor_version" -lt 3 ]] && compat=false
    ;;
  *)
    [[ "$major_version" -lt 16 ]] && compat=false
    ;;
esac

if [ $compat = false ]; then
  bashio::log.error "PostgreSQL version $pg_version is not supported. Please upgrade to v16.7 or later or v17.3 or later."
  exit 1
fi

if [[ -n $(PGPASSWORD="$DATABASE_PASS" psql -h "$DATABASE_HOST" -p "$DATABASE_PORT" -U "$DATABASE_USER" postgres -Atqc "SELECT datname FROM pg_database WHERE datname = '$DATABASE_NAME'") ]]; then
  bashio::log.info "Database $DATABASE_NAME already exists"
else
  if PGPASSWORD="$DATABASE_PASS" psql -h "$DATABASE_HOST" -p "$DATABASE_PORT" -U "$DATABASE_USER" postgres -qc "CREATE DATABASE \"$DATABASE_NAME\""; then
    bashio::log.info "Database $DATABASE_NAME created"
  else
    bashio::log.error "Failed to create database $DATABASE_NAME"
    exit 1
  fi
fi

# Import dashboards
if bashio::config.true 'grafana_import_dashboards'; then
    bashio::log.info "Importing Grafana dashboards..."
    /dashboards.sh restore || bashio::log.error "Failed to import dashboards"
fi

if [[ -z $(PGPASSWORD="$DATABASE_PASS" psql -h "$DATABASE_HOST" -p "$DATABASE_PORT" -U "$DATABASE_USER" "$DATABASE_NAME" -Atqc "SELECT 1 FROM settings WHERE base_url LIKE '%api/hassio_ingress%'" 2> /dev/null ) ]]; then
  teslamate_ingress=$(bashio::addon.ingress_entry)
  grafana_ingress=$(bashio::addon.ingress_entry "$(bashio::supervisor.addons | grep grafana)")
  if [[ "$teslamate_ingress" == "$grafana_ingress" ]]; then
    grafana_ingress="** Grafana addon not found. Ensure the addon is installed and running. **"
  fi

  bashio::log.notice ""
  bashio::log.notice "Configure TeslaMate settings by adding these values"
  bashio::log.notice "to the URL you use to access your Home Assistant instance:"
  bashio::log.notice ""
  bashio::log.notice "=> Web App: $teslamate_ingress"
  bashio::log.notice "=> Dashboards: $grafana_ingress"
  bashio::log.notice ""
fi

# Set max open file limit to avoid memory allocation issues
if [ "$(ulimit -Hn)" -gt 524288 ]; then
    ulimit -n 524288
fi

bashio::log.info "Starting TeslaMate..."

cd /opt/app
exec $(/usr/bin/env sh) /entrypoint.sh bin/teslamate start
