#!/usr/bin/env bash
#
# install_for_python - Provision the Python radio automation stack.
# Idempotent: safe to re-run. Derives the service name from this file's
# containing directory basename. Must be run as root.
#
set -euo pipefail

if [[ $EUID -ne 0 ]]; then
    echo "ERROR: this installer must be run as root." >&2
    exit 1
fi

INSTALL_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
SERVICE_NAME="$(basename "$INSTALL_DIR")"
UNIT_FILE="/etc/systemd/system/${SERVICE_NAME}.service"
LIQUIDSOAP_USER="liquidsoap"

echo "==> Installing ${SERVICE_NAME} (Python stack) from ${INSTALL_DIR}"

# ---------------------------------------------------------------------------
# 1. Base packages
# ---------------------------------------------------------------------------
echo "==> Ensuring base packages..."
export DEBIAN_FRONTEND=noninteractive
apt-get update -qq
apt-get install -y -qq \
    python3 python3-pip python3-venv \
    liquidsoap icecast2 jq curl ca-certificates >/dev/null

# Ensure the dedicated service user exists.
if ! id -u "$LIQUIDSOAP_USER" >/dev/null 2>&1; then
    useradd --system --create-home --shell /usr/sbin/nologin "$LIQUIDSOAP_USER"
    echo "    created system user '${LIQUIDSOAP_USER}'"
fi

# ---------------------------------------------------------------------------
# 2. Interactive configuration (defaults from existing config.json)
# ---------------------------------------------------------------------------
CONFIG_JSON="${INSTALL_DIR}/config.json"

prompt() {
    local var_name="$1" prompt_text="$2" default="${3:-}"
    local current=""
    if [[ -n "$default" ]]; then
        read -rp "${prompt_text} [${default}]: " current || true
        echo "${current:-$default}"
    else
        read -rp "${prompt_text}: " current || true
        echo "$current"
    fi
}

existing_storage="" ; existing_ic_host="" ; existing_ic_port=""
existing_ic_mount="" ; existing_ic_user="" ; existing_ic_pass=""
existing_gp_enable="" ; existing_gp_host="" ; existing_gp_user="" ; existing_gp_pass=""

if [[ -f "$CONFIG_JSON" ]]; then
    echo "==> Found existing config.json; using it for defaults."
    existing_storage=$(jq -r '.storage // empty' "$CONFIG_JSON")
    existing_ic_host=$(jq -r '.icecast.host // empty' "$CONFIG_JSON")
    existing_ic_port=$(jq -r '.icecast.port // empty' "$CONFIG_JSON")
    existing_ic_mount=$(jq -r '.icecast.mount // empty' "$CONFIG_JSON")
    existing_ic_user=$(jq -r '.icecast.username // empty' "$CONFIG_JSON")
    existing_ic_pass=$(jq -r '.icecast.password // empty' "$CONFIG_JSON")
    existing_gp_enable=$(jq -r '.gpodder.enable // empty' "$CONFIG_JSON")
    existing_gp_host=$(jq -r '.gpodder.host // empty' "$CONFIG_JSON")
    existing_gp_user=$(jq -r '.gpodder.username // empty' "$CONFIG_JSON")
    existing_gp_pass=$(jq -r '.gpodder.password // empty' "$CONFIG_JSON")
fi

echo ""
echo "--- Storage ---"
STORAGE_PATH=$(prompt storage_path "Storage path (media + state + logs)" "/mnt/storage/radio${existing_storage:+|$existing_storage}")
[[ -z "$STORAGE_PATH" ]] && STORAGE_PATH="${existing_storage:-/mnt/storage/radio}"

echo ""
echo "--- Icecast (source credentials) ---"
IC_HOST=$(prompt ic_host "Icecast host" "$existing_ic_host");           IC_HOST=${IC_HOST:-localhost}
IC_PORT=$(prompt ic_port "Icecast source port" "$existing_ic_port");     IC_PORT=${IC_PORT:-7777}
IC_MOUNT=$(prompt ic_mount "Mount point" "$existing_ic_mount");          IC_MOUNT=${IC_MOUNT:-/data}
IC_USER=$(prompt ic_user "Source username" "$existing_ic_user");         IC_USER=${IC_USER:-source}
read -rsp "Source password: " IC_PASS || true; echo;                   IC_PASS=${IC_PASS:-$existing_ic_pass}

echo ""
echo "--- gPodder sync (optional) ---"
GP_ENABLE=$(prompt gp_enable "Enable gPodder sync? (true/false)" "$existing_gp_enable"); GP_ENABLE=${GP_ENABLE:-false}
GP_HOST=$(prompt gp_host "gPodder host" "$existing_gp_host");            GP_HOST=${GP_HOST:-https://gpodder.net}
GP_USER=$(prompt gp_user "gPodder username" "$existing_gp_user")
read -rsp "gPodder password: " GP_PASS || true; echo;                  GP_PASS=${GP_PASS:-$existing_gp_pass}

echo ""
echo "Summary:"
echo "  Storage : $STORAGE_PATH"
echo "  Icecast : $IC_USER@$IC_HOST:$IC_PORT mount=$IC_MOUNT"
echo "  gPodder : enabled=$GP_ENABLE ($GP_USER @ $GP_HOST)"
read -rp "Proceed? [y/N]: " confirm || true
case "$confirm" in
    [Yy]*) ;;
    *) echo "Aborted."; exit 0 ;;
esac

# ---------------------------------------------------------------------------
# 3. Create the directory tree
# ---------------------------------------------------------------------------
echo "==> Creating directory tree under $STORAGE_PATH ..."
mkdir -p "$STORAGE_PATH"/{music,podcasts,jingles,announcements,state,playlists,logs}
chown -R "$LIQUIDSOAP_USER":"$LIQUIDSOAP_USER" "$STORAGE_PATH"

# ---------------------------------------------------------------------------
# 4. Write config.json (mode 600)
# ---------------------------------------------------------------------------
echo "==> Writing $CONFIG_JSON ..."
cat > "$CONFIG_JSON" <<EOF
{
  "storage": "${STORAGE_PATH}",
  "icecast": {
    "host": "${IC_HOST}",
    "port": ${IC_PORT},
    "mount": "${IC_MOUNT}",
    "username": "${IC_USER}",
    "password": "${IC_PASS}"
  },
  "gpodder": {
    "enable": $( [[ "$GP_ENABLE" =~ ^([Tt][Rr][Uu][Ee]|1)$ ]] && echo true || echo false ),
    "host": "${GP_HOST}",
    "username": "${GP_USER}",
    "password": "${GP_PASS}"
  }
}
EOF
chmod 600 "$CONFIG_JSON"
chown "$LIQUIDSOAP_USER":"$LIQUIDSOAP_USER" "$CONFIG_JSON"

# ---------------------------------------------------------------------------
# 5. Initialize BOTH SQLite databases with the full current schema.
#    This guarantees a known-good baseline at install time, independent of
#    which script runs first. Idempotent via IF NOT EXISTS.
# ---------------------------------------------------------------------------
echo "==> Initializing SQLite databases ..."
python3 - "$STORAGE_PATH/state" <<'PYINIT'
import sqlite3, sys, os
state_dir = sys.argv[1]

subs = os.path.join(state_dir, "subscriptions.db")
played = os.path.join(state_dir, "played.db")

conn = sqlite3.connect(subs)
conn.executescript("""
CREATE TABLE IF NOT EXISTS shows (
    slug TEXT PRIMARY KEY,
    guid TEXT NOT NULL UNIQUE,
    name TEXT NOT NULL,
    feed_url TEXT NOT NULL UNIQUE,
    source TEXT DEFAULT 'manual',
    opml_import INTEGER DEFAULT 0,
    archived INTEGER DEFAULT 1,
    created_at TEXT DEFAULT (datetime('now'))
);
""")
conn.commit(); conn.close()

conn = sqlite3.connect(played)
conn.executescript("""
CREATE TABLE IF NOT EXISTS episodes (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    show_slug TEXT NOT NULL,
    guid TEXT NOT NULL,
    title TEXT,
    file_path TEXT,
    enclosure_url TEXT,
    runlength INTEGER,
    played INTEGER DEFAULT 0,
    played_at TEXT,
    UNIQUE(show_slug, guid)
);
CREATE INDEX IF NOT EXISTS idx_episodes_show_played
    ON episodes (show_slug, played);
""")
conn.commit(); conn.close()

print("    subscriptions.db and played.db initialized.")
PYINIT
chown -R "$LIQUIDSOAP_USER":"$LIQUIDSOAP_USER" "$STORAGE_PATH/state"

# ---------------------------------------------------------------------------
# 6. Python virtualenv + dependencies
# ---------------------------------------------------------------------------
VENV="${INSTALL_DIR}/.venv"
if [[ ! -x "${VENV}/bin/python" ]]; then
    echo "==> Creating Python venv at ${VENV} ..."
    python3 -m venv "$VENV"
fi
echo "==> Installing Python dependencies (feedparser, requests) ..."
"${VENV}/bin/pip" install --quiet --upgrade pip
"${VENV}/bin/pip" install --quiet feedparser requests

# ---------------------------------------------------------------------------
# 7. systemd unit (named after the directory)
# ---------------------------------------------------------------------------
echo "==> Writing systemd unit ${UNIT_FILE} ..."
cat > "$UNIT_FILE" <<EOF
[Unit]
Description=Radio automation (${SERVICE_NAME}) - liquidsoap
After=network-online.target icecast2.service
Wants=network-online.target

[Service]
Type=simple
User=${LIQUIDSOAP_USER}
WorkingDirectory=${INSTALL_DIR}
ExecStart=${INSTALL_DIR}/.venv/bin/python ${INSTALL_DIR}/station_runner.py
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target
EOF

# Minimal runner that execs liquidsoap on station.liq from the install dir.
cat > "${INSTALL_DIR}/station_runner.py" <<'PYRUN'
import os, subprocess, sys
install_dir = os.path.dirname(os.path.abspath(__file__))
os.chdir(install_dir)
sys.exit(subprocess.call(["liquidsoap", os.path.join(install_dir, "station.liq")]))
PYRUN
chown "$LIQUIDSOAP_USER":"$LIQUIDSOAP_USER" "${INSTALL_DIR}/station_runner.py"

systemctl daemon-reload

# ---------------------------------------------------------------------------
# 8. Cron jobs (deduplicated)
# ---------------------------------------------------------------------------
echo "==> Setting up cron jobs ..."
FETCH_CRON="0 * * * * cd ${INSTALL_DIR} && ./.venv/bin/python fetch_podcasts.py >> ${STORAGE_PATH}/logs/fetch.log 2>&1"
UPDATE_CRON="30 * * * * cd ${INSTALL_DIR} && ./.venv/bin/python update_playlists.py >> ${STORAGE_PATH}/logs/update.log 2>&1"

crontab -l 2>/dev/null | grep -vF "fetch_podcasts.py" | grep -vF "update_playlists.py" > /tmp/cron_radio.$$ || true
echo "$FETCH_CRON"   >> /tmp/cron_radio.$$
echo "$UPDATE_CRON"  >> /tmp/cron_radio.$$
crontab /tmp/cron_radio.$$
rm -f /tmp/cron_radio.$$

# ---------------------------------------------------------------------------
# 9. Enable services
# ---------------------------------------------------------------------------
systemctl enable icecast2 "$SERVICE_NAME"
echo "==> Enabling icecast2 and ${SERVICE_NAME} at boot."

echo ""
echo "============================================================"
echo " Installation complete."
echo ""
echo " Next steps:"
echo "   1. Drop background music into ${STORAGE_PATH}/music/"
echo "   2. Edit ${INSTALL_DIR}/schedule.txt for scheduled shows"
echo "   3. Review ${INSTALL_DIR}/station.liq"
echo "   4. Start: systemctl start icecast2 ${SERVICE_NAME}"
echo "============================================================"
