#!/usr/bin/env bash
# =============================================================================
# onx-mailbox-quota — Update a mailbox quota (Dovecot SQL + recalc)
#
# Input (stdin JSON):
#   {
#     "email":    "user@example.com",   -- required
#     "quota_mb": 2048                  -- required; -1 = unlimited
#   }
#
# Output (stdout JSON):
#   {
#     "email":        "...",
#     "quota_mb":     2048,
#     "quota_bytes":  2147483648,
#     "recalculated": true|false,
#     "updated":      true
#   }
#
# Exit codes: 0=ok 1=invalid 2=preflight 3=exec
#
# Deployed to: /usr/local/onoxsoft/bin/onx-mailbox-quota
# =============================================================================

set -euo pipefail

SCRIPT_DIR="$(dirname "$(readlink -f "$0")")"
# shellcheck source=_lib/common.sh
source "${SCRIPT_DIR}/_lib/common.sh"

require_root
if [[ "${MOCK_MODE}" != "1" ]]; then
    command -v doveadm >/dev/null 2>&1 || onx_die 2 "doveadm not found"
    command -v mysql   >/dev/null 2>&1 || onx_die 2 "mysql client not found"
fi

onx_json_input

EMAIL_RAW=$(onx_json_field "email")
QUOTA_MB=$(onx_json_field  "quota_mb")

onx_validate_email "${EMAIL_RAW}" >/dev/null
EMAIL="${ONX_EMAIL}"
[[ -z "${QUOTA_MB}" ]] && onx_die 1 "quota_mb is required"
[[ "${QUOTA_MB}" =~ ^-?[0-9]+$ ]] || onx_die 1 "quota_mb must be integer"

# Compute bytes (0 = unlimited per Dovecot convention; negative quota_mb
# also maps to 0 so the panel can use -1 as a sentinel).
QUOTA_BYTES=$(( QUOTA_MB * 1024 * 1024 ))
[[ "${QUOTA_MB}" -lt 0 ]] && QUOTA_BYTES=0

# ── Confirm the mailbox exists ───────────────────────────────────────────────
COUNT=$(mysql_exec "${DOVECOT_DB_NAME}" \
    "SELECT COUNT(*) FROM dovecot_users WHERE email='${EMAIL}';" 2>/dev/null | tail -1)
COUNT="${COUNT:-0}"
if [[ "${MOCK_MODE}" != "1" ]] && [[ "${COUNT}" == "0" ]]; then
    onx_die 2 "mailbox not found: ${EMAIL}"
fi

# ── Update quota ─────────────────────────────────────────────────────────────
mysql_exec "${DOVECOT_DB_NAME}" \
    "UPDATE dovecot_users SET quota_bytes=${QUOTA_BYTES}, updated_at=NOW() WHERE email='${EMAIL}';" \
    || onx_die 3 "dovecot_users UPDATE failed for ${EMAIL}"

# ── Recalc on-disk quota dict ────────────────────────────────────────────────
# `doveadm quota recalc` walks the Maildir and writes the new totals to the
# quota dictionary (used by IMAP QUOTA extension). Non-fatal on failure;
# the next mail action will trigger a lazy recalc anyway.
RECALCED="false"
if [[ "${MOCK_MODE}" != "1" ]] && command -v doveadm >/dev/null 2>&1; then
    if doveadm quota recalc -u "${EMAIL}" 2>/dev/null; then
        RECALCED="true"
    else
        onx_log "doveadm quota recalc failed for ${EMAIL} (lazy recalc on next mail)"
    fi
fi

onx_audit "onx-mailbox" "quota-change email=${EMAIL} quota_mb=${QUOTA_MB} recalc=${RECALCED}"

onx_json_out \
    "email"        "${EMAIL}" \
    "quota_mb"     "${QUOTA_MB}" \
    "quota_bytes"  "${QUOTA_BYTES}" \
    "recalculated" "${RECALCED}" \
    "updated"      "true"
