#!/usr/bin/env bash
set -euo pipefail

NAS_ROOT="${NAS_ROOT:-/Volumes/docker/nodedc-platform}"
NAS_PLATFORM_DIR="${NAS_PLATFORM_DIR:-/volume1/docker/nodedc-platform/platform}"
NAS_TASKER_DIR="${NAS_TASKER_DIR:-/volume1/docker/nodedc-platform/tasker/plane-app}"
NAS_GATEWAY_DIR="${NAS_GATEWAY_DIR:-/volume1/docker/nodedc-platform/ops-agents}"
BACKUP_ROOT="${BACKUP_ROOT:-${NAS_ROOT}/backups}"
TIMESTAMP="${TIMESTAMP:-$(date +%Y%m%d-%H%M%S)}"
BACKUP_DIR="${BACKUP_DIR:-${BACKUP_ROOT}/platform-current-${TIMESTAMP}}"
DOCKER_BIN="${DOCKER_BIN:-/usr/local/bin/docker}"
COMPOSE_FILE="${COMPOSE_FILE:-${NAS_PLATFORM_DIR}/docker-compose.platform-http.yml}"
ENV_FILE="${ENV_FILE:-${NAS_PLATFORM_DIR}/.env.synology}"

mkdir -p "${BACKUP_DIR}/files/platform" \
  "${BACKUP_DIR}/files/launcher" \
  "${BACKUP_DIR}/files/authentik" \
  "${BACKUP_DIR}/files/tasker" \
  "${BACKUP_DIR}/files/ops-agents" \
  "${BACKUP_DIR}/files/bim-viewer"

rsync_dir() {
  local source="$1"
  local destination="$2"

  if [[ -e "${source}" ]]; then
    rsync -a --delete "${source}" "${destination}"
  else
    echo "skip missing: ${source}" | tee -a "${BACKUP_DIR}/warnings.log" >&2
  fi
}

rsync_file() {
  local source="$1"
  local destination="$2"

  if [[ -f "${source}" ]]; then
    rsync -a "${source}" "${destination}"
  else
    echo "skip missing: ${source}" | tee -a "${BACKUP_DIR}/warnings.log" >&2
  fi
}

rsync_dir "${NAS_ROOT}/launcher/server-storage/" "${BACKUP_DIR}/files/launcher/server-storage/"
rsync_dir "${NAS_ROOT}/launcher/uploads/" "${BACKUP_DIR}/files/launcher/uploads/"
rsync_dir "${NAS_ROOT}/authentik/custom-templates/" "${BACKUP_DIR}/files/authentik/custom-templates/"
rsync_dir "${NAS_ROOT}/platform/authentik/" "${BACKUP_DIR}/files/platform/authentik/"
rsync_dir "${NAS_ROOT}/platform/notification-core/" "${BACKUP_DIR}/files/platform/notification-core/"
rsync_dir "${NAS_ROOT}/platform/ai-workspace-hub/" "${BACKUP_DIR}/files/platform/ai-workspace-hub/"
rsync_dir "${NAS_ROOT}/platform/ai-workspace-assistant/" "${BACKUP_DIR}/files/platform/ai-workspace-assistant/"
rsync_dir "${NAS_ROOT}/platform/ontology-core/" "${BACKUP_DIR}/files/platform/ontology-core/"
rsync_dir "${NAS_ROOT}/bim-viewer/source/server/data/" "${BACKUP_DIR}/files/bim-viewer/server-data/"

rsync_file "${NAS_ROOT}/platform/.env.synology" "${BACKUP_DIR}/files/platform/"
rsync_file "${NAS_ROOT}/platform/.env.synology.example" "${BACKUP_DIR}/files/platform/"
rsync_file "${NAS_ROOT}/platform/docker-compose.platform-http.yml" "${BACKUP_DIR}/files/platform/"
rsync_file "${NAS_ROOT}/platform/Caddyfile.http" "${BACKUP_DIR}/files/platform/"

rsync_file "${NAS_ROOT}/tasker/plane-app/.env.synology" "${BACKUP_DIR}/files/tasker/"
rsync_file "${NAS_ROOT}/tasker/plane-app/docker-compose.yaml" "${BACKUP_DIR}/files/tasker/"
rsync_file "${NAS_ROOT}/tasker/plane-app/docker-compose.synology.override.yml" "${BACKUP_DIR}/files/tasker/"

rsync_file "${NAS_ROOT}/ops-agents/.env" "${BACKUP_DIR}/files/ops-agents/"
rsync_file "${NAS_ROOT}/ops-agents/.env.synology.example" "${BACKUP_DIR}/files/ops-agents/"
rsync_file "${NAS_ROOT}/ops-agents/docker-compose.synology.yml" "${BACKUP_DIR}/files/ops-agents/"

rsync_file "${NAS_ROOT}/bim-viewer/source/.env" "${BACKUP_DIR}/files/bim-viewer/"
rsync_file "${NAS_ROOT}/bim-viewer/source/.env.synology.example" "${BACKUP_DIR}/files/bim-viewer/"
rsync_file "${NAS_ROOT}/bim-viewer/source/docker-compose.beam.yml" "${BACKUP_DIR}/files/bim-viewer/"

cat > "${BACKUP_DIR}/manifest.txt" <<EOF
NODE.DC platform current backup
timestamp=${TIMESTAMP}
nas_root=${NAS_ROOT}
backup_dir=${BACKUP_DIR}

Contains:
- Launcher runtime snapshot: launcher/server-storage
- Launcher uploads: launcher/uploads
- Authentik custom templates: authentik/custom-templates
- Platform runtime config: platform/.env.synology, compose, Caddyfile
- Notification Core source/config: platform/notification-core, platform compose/env
- AI Workspace Hub source/config: platform/ai-workspace-hub, platform compose/env
- AI Workspace Assistant source/config: platform/ai-workspace-assistant, platform compose/env
- Ontology Core source/catalog: platform/ontology-core, platform compose/env
- Tasker runtime config: tasker/plane-app/.env.synology, compose, Synology override
- Ops Agents Gateway runtime config: ops-agents/.env, compose
- BIM Viewer runtime data/config: bim-viewer/source/server/data, .env, compose

Secrets:
- files/platform/.env.synology contains live secrets.
- files/tasker/.env.synology contains live secrets.
- files/ops-agents/.env contains live secrets.
- files/bim-viewer/.env contains live secrets.
- Keep this backup private.
EOF

cat > "${BACKUP_DIR}/run-authentik-db-dump-on-synology.sh" <<EOF
#!/usr/bin/env bash
set -euo pipefail

BACKUP_DIR="/volume1/docker/nodedc-platform/backups/$(basename "${BACKUP_DIR}")"
cd "${NAS_PLATFORM_DIR}"

sudo "${DOCKER_BIN}" compose \\
  --env-file "${ENV_FILE}" \\
  -f "${COMPOSE_FILE}" \\
  exec -T postgresql-authentik \\
  sh -lc 'pg_dump -U "\${POSTGRES_USER:-authentik}" -d "\${POSTGRES_DB:-authentik}" --format=custom --no-owner --no-acl' \\
  > "\${BACKUP_DIR}/authentik-postgres.dump"

sudo "${DOCKER_BIN}" compose \\
  --env-file "${ENV_FILE}" \\
  -f "${COMPOSE_FILE}" \\
  exec -T postgresql-authentik \\
  rm -f /tmp/authentik-postgres.dump

sudo "${DOCKER_BIN}" compose \\
  --env-file "${ENV_FILE}" \\
  -f "${COMPOSE_FILE}" \\
  cp "\${BACKUP_DIR}/authentik-postgres.dump" postgresql-authentik:/tmp/authentik-postgres.dump

sudo "${DOCKER_BIN}" compose \\
  --env-file "${ENV_FILE}" \\
  -f "${COMPOSE_FILE}" \\
  exec -T postgresql-authentik \\
  pg_restore --list /tmp/authentik-postgres.dump >/dev/null

sudo "${DOCKER_BIN}" compose \\
  --env-file "${ENV_FILE}" \\
  -f "${COMPOSE_FILE}" \\
  exec -T postgresql-authentik \\
  rm -f /tmp/authentik-postgres.dump

if command -v sha256sum >/dev/null 2>&1; then
  (cd "\${BACKUP_DIR}" && sha256sum authentik-postgres.dump > SHA256SUMS)
else
  (cd "\${BACKUP_DIR}" && shasum -a 256 authentik-postgres.dump > SHA256SUMS)
fi

echo "authentik-db-dump-ok: \${BACKUP_DIR}/authentik-postgres.dump"
EOF
chmod +x "${BACKUP_DIR}/run-authentik-db-dump-on-synology.sh"

cat > "${BACKUP_DIR}/run-notification-db-dump-on-synology.sh" <<EOF
#!/usr/bin/env bash
set -euo pipefail

BACKUP_DIR="/volume1/docker/nodedc-platform/backups/$(basename "${BACKUP_DIR}")"
cd "${NAS_PLATFORM_DIR}"

sudo "${DOCKER_BIN}" compose \\
  --env-file "${ENV_FILE}" \\
  -f "${COMPOSE_FILE}" \\
  exec -T notification-postgres \\
  sh -lc 'pg_dump -U "\${POSTGRES_USER:-nodedc_notifications}" -d "\${POSTGRES_DB:-nodedc_notifications}" --format=custom --no-owner --no-acl' \\
  > "\${BACKUP_DIR}/notification-postgres.dump"

sudo "${DOCKER_BIN}" compose \\
  --env-file "${ENV_FILE}" \\
  -f "${COMPOSE_FILE}" \\
  exec -T notification-postgres \\
  rm -f /tmp/notification-postgres.dump

sudo "${DOCKER_BIN}" compose \\
  --env-file "${ENV_FILE}" \\
  -f "${COMPOSE_FILE}" \\
  cp "\${BACKUP_DIR}/notification-postgres.dump" notification-postgres:/tmp/notification-postgres.dump

sudo "${DOCKER_BIN}" compose \\
  --env-file "${ENV_FILE}" \\
  -f "${COMPOSE_FILE}" \\
  exec -T notification-postgres \\
  pg_restore --list /tmp/notification-postgres.dump >/dev/null

sudo "${DOCKER_BIN}" compose \\
  --env-file "${ENV_FILE}" \\
  -f "${COMPOSE_FILE}" \\
  exec -T notification-postgres \\
  rm -f /tmp/notification-postgres.dump

echo "notification-db-dump-ok: \${BACKUP_DIR}/notification-postgres.dump"
EOF
chmod +x "${BACKUP_DIR}/run-notification-db-dump-on-synology.sh"

cat > "${BACKUP_DIR}/run-tasker-db-dump-on-synology.sh" <<EOF
#!/usr/bin/env bash
set -euo pipefail

BACKUP_DIR="/volume1/docker/nodedc-platform/backups/$(basename "${BACKUP_DIR}")"
cd "${NAS_TASKER_DIR}"

compose_args=(compose -p nodedc-tasker --env-file .env.synology -f docker-compose.yaml)
if [[ -f docker-compose.synology.override.yml ]]; then
  compose_args+=(-f docker-compose.synology.override.yml)
fi

sudo "${DOCKER_BIN}" "\${compose_args[@]}" \\
  exec -T plane-db \\
  sh -lc 'pg_dump -U "\${POSTGRES_USER:-plane}" -d "\${POSTGRES_DB:-plane}" --format=custom --no-owner --no-acl' \\
  > "\${BACKUP_DIR}/tasker-postgres.dump"

sudo "${DOCKER_BIN}" "\${compose_args[@]}" \\
  exec -T plane-db \\
  rm -f /tmp/tasker-postgres.dump

sudo "${DOCKER_BIN}" "\${compose_args[@]}" \\
  cp "\${BACKUP_DIR}/tasker-postgres.dump" plane-db:/tmp/tasker-postgres.dump

sudo "${DOCKER_BIN}" "\${compose_args[@]}" \\
  exec -T plane-db \\
  pg_restore --list /tmp/tasker-postgres.dump >/dev/null

sudo "${DOCKER_BIN}" "\${compose_args[@]}" \\
  exec -T plane-db \\
  rm -f /tmp/tasker-postgres.dump

echo "tasker-db-dump-ok: \${BACKUP_DIR}/tasker-postgres.dump"
EOF
chmod +x "${BACKUP_DIR}/run-tasker-db-dump-on-synology.sh"

cat > "${BACKUP_DIR}/run-ops-agents-db-dump-on-synology.sh" <<EOF
#!/usr/bin/env bash
set -euo pipefail

BACKUP_DIR="/volume1/docker/nodedc-platform/backups/$(basename "${BACKUP_DIR}")"
cd "${NAS_GATEWAY_DIR}"

sudo "${DOCKER_BIN}" compose \\
  --env-file .env \\
  -f docker-compose.synology.yml \\
  exec -T postgres \\
  sh -lc 'pg_dump -U "\${POSTGRES_USER:-nodedc_agent_gateway}" -d "\${POSTGRES_DB:-nodedc_agent_gateway}" --format=custom --no-owner --no-acl' \\
  > "\${BACKUP_DIR}/ops-agents-postgres.dump"

sudo "${DOCKER_BIN}" compose \\
  --env-file .env \\
  -f docker-compose.synology.yml \\
  exec -T postgres \\
  rm -f /tmp/ops-agents-postgres.dump

sudo "${DOCKER_BIN}" compose \\
  --env-file .env \\
  -f docker-compose.synology.yml \\
  cp "\${BACKUP_DIR}/ops-agents-postgres.dump" postgres:/tmp/ops-agents-postgres.dump

sudo "${DOCKER_BIN}" compose \\
  --env-file .env \\
  -f docker-compose.synology.yml \\
  exec -T postgres \\
  pg_restore --list /tmp/ops-agents-postgres.dump >/dev/null

sudo "${DOCKER_BIN}" compose \\
  --env-file .env \\
  -f docker-compose.synology.yml \\
  exec -T postgres \\
  rm -f /tmp/ops-agents-postgres.dump

echo "ops-agents-db-dump-ok: \${BACKUP_DIR}/ops-agents-postgres.dump"
EOF
chmod +x "${BACKUP_DIR}/run-ops-agents-db-dump-on-synology.sh"

find "${BACKUP_DIR}" -name @eaDir -prune -o -type d -exec chmod 700 {} \;
find "${BACKUP_DIR}" -name @eaDir -prune -o -type f -exec chmod 600 {} \;
chmod 700 "${BACKUP_DIR}/run-authentik-db-dump-on-synology.sh"
chmod 700 "${BACKUP_DIR}/run-notification-db-dump-on-synology.sh"
chmod 700 "${BACKUP_DIR}/run-tasker-db-dump-on-synology.sh"
chmod 700 "${BACKUP_DIR}/run-ops-agents-db-dump-on-synology.sh"

if [[ -x "${DOCKER_BIN}" && "${NAS_ROOT}" == /volume1/* ]]; then
  "${BACKUP_DIR}/run-authentik-db-dump-on-synology.sh"
  "${BACKUP_DIR}/run-notification-db-dump-on-synology.sh"
else
  cat <<EOF
file-backup-ok: ${BACKUP_DIR}

DB dump was not run from this host.
Run on Synology:

bash /volume1/docker/nodedc-platform/backups/$(basename "${BACKUP_DIR}")/run-authentik-db-dump-on-synology.sh

bash /volume1/docker/nodedc-platform/backups/$(basename "${BACKUP_DIR}")/run-notification-db-dump-on-synology.sh

# If Tasker database exists and backend/schema changes are planned:
bash /volume1/docker/nodedc-platform/backups/$(basename "${BACKUP_DIR}")/run-tasker-db-dump-on-synology.sh

# If Ops Agents Gateway was already deployed:
bash /volume1/docker/nodedc-platform/backups/$(basename "${BACKUP_DIR}")/run-ops-agents-db-dump-on-synology.sh
EOF
fi
