#!/bin/bash
# install.sh — generate and install sky-cam systemd units from sky-cam.conf.
#
# Usage:
#   ./install.sh           # installs to ~/.config/systemd/user (no root needed)
#   ./install.sh --system  # installs to /etc/systemd/system    (needs sudo)
#
# Run this once after editing sky-cam.conf, and again whenever sky-cam.conf
# changes (e.g. SCRIPT_DIR moves, cameras added, schedules changed).
# No other file needs editing.

set -euo pipefail

HERE="$(dirname "$(realpath "$0")")"
source "$HERE/sky-cam.conf"

# ── Install target ────────────────────────────────────────────────────────────
SYSTEM_MODE=false
[ "${1:-}" = "--system" ] && SYSTEM_MODE=true

if $SYSTEM_MODE; then
    UNIT_DIR="/etc/systemd/system"
    SC="sudo systemctl"
else
    UNIT_DIR="$HOME/.config/systemd/user"
    SC="systemctl --user"
fi

mkdir -p "$UNIT_DIR"
echo "Installing systemd units to $UNIT_DIR ..."

# ── Helper: write a oneshot service unit ─────────────────────────────────────
write_service() {
    local unit="$1" description="$2" script="$3" extra="${4:-}"
    cat > "$UNIT_DIR/${unit}.service" <<EOF
[Unit]
Description=Sky-Cam — $description
${extra}OnFailure=sky-cam-notify-failure@%n.service

[Service]
Type=oneshot
ExecStart=$SCRIPT_DIR/$script
StandardOutput=journal
StandardError=journal
EOF
    echo "  wrote ${unit}.service"
}

# ── Helper: write a timer unit ───────────────────────────────────────────────
write_timer() {
    local unit="$1" description="$2" calendar="$3"
    cat > "$UNIT_DIR/${unit}.timer" <<EOF
[Unit]
Description=Sky-Cam — $description

[Timer]
OnCalendar=*-*-* $calendar
Persistent=true

[Install]
WantedBy=timers.target
EOF
    echo "  wrote ${unit}.timer"
}

# ── Failure notification template ────────────────────────────────────────────
cat > "$UNIT_DIR/sky-cam-notify-failure@.service" <<EOF
[Unit]
Description=Sky-Cam notify on failure for %i

[Service]
Type=oneshot
ExecStart=$SCRIPT_DIR/notify.sh "sky-cam job failed: %i" "systemd unit %i failed — check: journalctl -u %i"
EOF
echo "  wrote sky-cam-notify-failure@.service"

# ── Sunrise video — SUNRISE_CAM only ─────────────────────────────────────────
# OnSuccess= triggers the upload service only when video creation succeeds.
cat > "$UNIT_DIR/sky-cam-sunrise.service" <<EOF
[Unit]
Description=Sky-Cam — $SUNRISE_CAM: daily sunrise video
After=network-online.target
Wants=network-online.target
OnFailure=sky-cam-notify-failure@%n.service
OnSuccess=sky-cam-sunrise-upload.service

[Service]
Type=oneshot
ExecStart=$SCRIPT_DIR/daily_sunrise_video.sh $SUNRISE_CAM
StandardOutput=journal
StandardError=journal
EOF
echo "  wrote sky-cam-sunrise.service"

cat > "$UNIT_DIR/sky-cam-sunrise-upload.service" <<EOF
[Unit]
Description=Sky-Cam — $SUNRISE_CAM: upload daily sunrise to Mattermost
After=network-online.target
Wants=network-online.target
OnFailure=sky-cam-notify-failure@%n.service

[Service]
Type=oneshot
ExecStart=$SCRIPT_DIR/sunrise2mm.py
StandardOutput=journal
StandardError=journal
EOF
echo "  wrote sky-cam-sunrise-upload.service"

write_timer "sky-cam-sunrise" "$SUNRISE_CAM: daily sunrise video" "$SCHEDULE_SUNRISE"

timers=(sky-cam-sunrise)

# ── Per-camera continuous capture services ────────────────────────────────────
# capture.sh replaces MotionEye / any NVR for periodic JPEG capture.
# Generated when CAM_RTSP_<cam> is set; Type=simple (long-running, not oneshot).
capture_services=()
for cam in "${CAMERAS[@]}"; do
    rtsp_var="CAM_RTSP_${cam}"
    if [ -n "${!rtsp_var:-}" ]; then
        cat > "$UNIT_DIR/sky-cam-capture-${cam}.service" <<EOF
[Unit]
Description=Sky-Cam — ${cam}: continuous RTSP frame capture
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
ExecStart=$SCRIPT_DIR/capture.sh ${cam}
Restart=on-failure
RestartSec=30
StandardOutput=journal
StandardError=journal

[Install]
WantedBy=default.target
EOF
        echo "  wrote sky-cam-capture-${cam}.service"
        capture_services+=("sky-cam-capture-${cam}")

        cat > "$UNIT_DIR/sky-cam-watchdog-${cam}.service" <<EOF
[Unit]
Description=Sky-Cam — ${cam}: capture watchdog (stall detection)
After=sky-cam-capture-${cam}.service
Wants=sky-cam-capture-${cam}.service

[Service]
Type=simple
ExecStart=$SCRIPT_DIR/capture-watchdog.sh ${cam}
Restart=on-failure
RestartSec=10
StandardOutput=journal
StandardError=journal

[Install]
WantedBy=default.target
EOF
        echo "  wrote sky-cam-watchdog-${cam}.service"
        capture_services+=("sky-cam-watchdog-${cam}")
    else
        echo "  WARNING: CAM_RTSP_${cam} not set — skipping capture service for ${cam}"
        echo "           (set CAM_RTSP_${cam}=rtsp://... in sky-cam.conf to enable)"
    fi
done

# ── Sunrise audio capture ─────────────────────────────────────────────────────
# Uses the same schedule as the sunrise video — both start early and wait
# internally for the right moment, so they don't interfere.
if [ "${AUDIO_ENABLED:-false}" = "true" ]; then
    write_service "sky-cam-audio-capture" \
        "$SUNRISE_CAM: sunrise audio capture" \
        "sunrise-audio-capture.sh"
    write_timer "sky-cam-audio-capture" \
        "$SUNRISE_CAM: sunrise audio capture" \
        "$SCHEDULE_SUNRISE"
    timers+=("sky-cam-audio-capture")
fi

# ── Per-camera Four Seasons jobs ─────────────────────────────────────────────
# Reads CAMERAS and SCHEDULE_SEASONS_<cam> from sky-cam.conf.
# Script receives the camera name as $1 so it knows which camera to process.
for cam in "${CAMERAS[@]}"; do
    sched_seasons_var="SCHEDULE_SEASONS_${cam}"

    if [ -n "${!sched_seasons_var:-}" ]; then
        write_service "sky-cam-seasons-${cam}" \
            "${cam}: Four Seasons daily clip" \
            "4-seasons.sh ${cam}" \
            $'After=network-online.target\nWants=network-online.target\n'
        write_timer "sky-cam-seasons-${cam}" "${cam}: Four Seasons daily clip" \
            "${!sched_seasons_var}"
        timers+=("sky-cam-seasons-${cam}")
    else
        echo "  WARNING: SCHEDULE_SEASONS_${cam} not set — skipping seasons timer for ${cam}"
    fi
done

# ── Generate .env.example ────────────────────────────────────────────────────
env_example="$HERE/.env.example"
{
    echo "# sky-cam credentials — copy to .env and fill in real values."
    echo "# .env is gitignored and never checked in."
    echo ""
    echo "# RTSP stream URLs — one line per camera (variable name = CAM_RTSP_<camname>)"
    for cam in "${CAMERAS[@]}"; do
        echo "CAM_RTSP_${cam}=rtsp://admin:PASSWORD@192.168.1.XXX:554/stream1"
    done
    echo ""
    echo "# Mattermost upload"
    echo "mattermost_url=https://your-mattermost-server.example.com"
    echo "access_token=your-access-token-here"
    echo "channel_id=your-daily-upload-channel-id-here"
    echo ""
    echo "# Notifications (uncomment whichever you use)"
    echo "#NTFY_URL=https://ntfy.sh/your-topic"
    echo "#EMAIL_TO=you@example.com"
    echo "#MM_NOTIFY_CHANNEL_ID=your-notify-channel-id-here"
} > "$env_example"
echo "  wrote .env.example  (cp .env.example .env  then fill in real values)"

# ── Reload and enable ─────────────────────────────────────────────────────────
echo ""
$SC daemon-reload

for svc in "${capture_services[@]}"; do
    $SC enable --now "${svc}.service" \
        && echo "  enabled + started ${svc}.service" \
        || echo "  WARNING: could not enable ${svc}.service"
done

for timer in "${timers[@]}"; do
    $SC enable --now "${timer}.timer" \
        && echo "  enabled + started ${timer}.timer" \
        || echo "  WARNING: could not enable ${timer}.timer"
done

echo ""
echo "Done. Check status with:"
if $SYSTEM_MODE; then
    echo "  sudo systemctl list-timers 'sky-cam-*'"
    echo "  sudo journalctl -u sky-cam-seasons-${CAMERAS[0]}.service -f"
else
    echo "  systemctl --user list-timers 'sky-cam-*'"
    echo "  journalctl --user -u sky-cam-seasons-${CAMERAS[0]}.service -f"
fi
