#!/usr/bin/env bash
# Privileged Maildir filesystem helper for Limristem eMail.
# Invoked as root via sudo from the API so mailboxes are created with vmail ownership
# even when the app runs as limristem-mail (API / panel / import job setup).
set -Eeuo pipefail

SCRIPT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
if [[ -x "$SCRIPT_DIR/../limristem-mail" ]]; then
  BASE_DIR=$(cd "$SCRIPT_DIR/.." && pwd)
elif [[ -x "$SCRIPT_DIR/../../limristem-mail" ]]; then
  BASE_DIR=$(cd "$SCRIPT_DIR/../.." && pwd)
else
  BASE_DIR=$(cd "$SCRIPT_DIR/.." && pwd)
fi

# shellcheck source=/dev/null
if [[ -f "$SCRIPT_DIR/libenv.sh" ]]; then
  source "$SCRIPT_DIR/libenv.sh"
elif [[ -f "$BASE_DIR/bin/libenv.sh" ]]; then
  source "$BASE_DIR/bin/libenv.sh"
fi

for envf in \
  "$BASE_DIR/config/limristem-mail.env" \
  /etc/limristem-mail.env
do
  if [[ -f "$envf" ]]; then
    # shellcheck disable=SC1090
    set -a
    # Prefer libenv loader when available
    if declare -F limristem_mail_load_env_file >/dev/null 2>&1; then
      limristem_mail_load_env_file "$envf" || true
    else
      # shellcheck disable=SC1090
      source <(grep -E '^LIMRISTEM_MAIL_[A-Z0-9_]+=' "$envf" | sed 's/^/export /') || true
    fi
    set +a
    break
  fi
done

MAIL_HOME=${LIMRISTEM_MAIL_MAIL_HOME:-/var/mail/vhosts}
VMAIL_UID=${LIMRISTEM_MAIL_VMAIL_UID:-150}
VMAIL_GID=${LIMRISTEM_MAIL_VMAIL_GID:-150}
if id vmail >/dev/null 2>&1; then
  VMAIL_UID=$(id -u vmail)
  VMAIL_GID=$(id -g vmail)
fi

usage() {
  cat <<'EOF'
Usage: manage-mailbox-fs.sh <command> [args]

Commands:
  ensure-maildir <domain> <local_part>   Create Maildir++ tree owned by vmail
  ensure-mail-home                       Ensure MAIL_HOME permissions for API writes
EOF
}

is_safe_label() {
  local value=$1
  [[ -n "$value" && ${#value} -le 255 && "$value" =~ ^[A-Za-z0-9]([A-Za-z0-9._-]*[A-Za-z0-9])?$ ]]
}

ensure_mail_home() {
  mkdir -p "$MAIL_HOME"
  # setgid + group-writable so limristem-mail (member of vmail) can create trees,
  # then chown to vmail when CAP_CHOWN or root is available.
  chown vmail:vmail "$MAIL_HOME" 2>/dev/null || chown "${VMAIL_UID}:${VMAIL_GID}" "$MAIL_HOME"
  chmod 2770 "$MAIL_HOME"
  if id limristem-mail >/dev/null 2>&1; then
    usermod -a -G vmail limristem-mail 2>/dev/null || true
  fi
}

ensure_maildir() {
  local domain=$1
  local local_part=$2
  local domain_dir mailbox special sub

  if ! is_safe_label "$domain"; then
    echo "Invalid domain label: $domain" >&2
    exit 2
  fi
  # Path-safe local part (no separators / traversal). Full RFC validation is done by the API.
  if [[ -z "$local_part" || ${#local_part} -gt 64 ]]; then
    echo "Invalid local part: $local_part" >&2
    exit 2
  fi
  if [[ "$local_part" == *"/"* || "$local_part" == *"\\"* || "$local_part" == *".."* || "$local_part" == *..* ]]; then
    echo "Invalid local part path component: $local_part" >&2
    exit 2
  fi
  if [[ "$domain" == *..* || "$domain" == *"/"* ]]; then
    echo "Invalid domain path component" >&2
    exit 2
  fi

  ensure_mail_home
  domain_dir="$MAIL_HOME/$domain"
  mailbox="$domain_dir/$local_part"
  mkdir -p "$mailbox"/{cur,new,tmp}
  for special in Sent Drafts Junk Trash Archive; do
    mkdir -p "$mailbox/.${special}"/{cur,new,tmp}
  done
  mkdir -p "$mailbox/sieve"
  if [[ ! -f "$mailbox/subscriptions" ]]; then
    printf '%s\n' Archive Drafts Junk Sent Trash | sort > "$mailbox/subscriptions"
  fi
  chown -R "${VMAIL_UID}:${VMAIL_GID}" "$domain_dir"
  chmod 2770 "$domain_dir"
  chmod 700 "$mailbox"
  find "$mailbox" -mindepth 1 -type d -exec chmod 700 {} +
  chmod 600 "$mailbox/subscriptions" 2>/dev/null || true
  # sieve dir stays private
  chmod 700 "$mailbox/sieve" 2>/dev/null || true
  printf 'ok %s\n' "$mailbox"
}

cmd=${1:-}
shift || true

case "$cmd" in
  ensure-maildir)
    [[ $# -ge 2 ]] || { echo "Usage: manage-mailbox-fs.sh ensure-maildir <domain> <local_part>" >&2; exit 2; }
    ensure_maildir "$1" "$2"
    ;;
  ensure-mail-home)
    ensure_mail_home
    echo "ok $MAIL_HOME"
    ;;
  -h|--help|help|"")
    usage
    exit 0
    ;;
  *)
    echo "Unknown command: $cmd" >&2
    usage >&2
    exit 2
    ;;
esac
