#!/usr/bin/env bash
# =============================================================================
# onx-mailbox-password — Change a mailbox password (Dovecot SQL backend)
#
# Input (stdin JSON):
#   {
#     "email":        "user@example.com",   -- required
#     "new_password": "<plaintext>"         -- required
#   }
#
# Output (stdout JSON):
#   {
#     "email":         "...",
#     "password_hash": "{SHA512-CRYPT}...",
#     "kicked":        true|false,
#     "updated":       true
#   }
#
# Side effects:
#   - UPDATE dovecot_users SET password=?,updated_at=NOW() WHERE email=?
#   - doveadm kick <email>   (force re-auth on existing IMAP/POP3 sessions)
#
# Exit codes: 0=ok 1=invalid 2=preflight 3=exec
#
# Deployed to: /usr/local/onoxsoft/bin/onx-mailbox-password
# =============================================================================

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")
NEW_PASSWORD=$(onx_json_field "new_password")

onx_validate_email "${EMAIL_RAW}" >/dev/null
EMAIL="${ONX_EMAIL}"
[[ -z "${NEW_PASSWORD}" ]] && onx_die 1 "new_password is required"

# Refuse trivially short passwords. Panel-level UX already enforces 8+ chars
# but we keep a backstop here for direct API consumers.
if [[ "${#NEW_PASSWORD}" -lt 8 ]]; then
    onx_die 1 "new_password too short (minimum 8 characters)"
fi

# ── 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

# ── Hash new password ────────────────────────────────────────────────────────
PASSWORD_HASH=$(onx_doveadm_pw "${NEW_PASSWORD}")
[[ -z "${PASSWORD_HASH}" ]] && onx_die 3 "password hash empty (doveadm failure)"
PASSWORD_HASH_ESC="${PASSWORD_HASH//\'/\\\'}"

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

# ── Kick active sessions ─────────────────────────────────────────────────────
KICKED="false"
if [[ "${MOCK_MODE}" != "1" ]] && command -v doveadm >/dev/null 2>&1; then
    # doveadm kick returns non-zero when no sessions are active — we don't
    # treat that as an error, just record it.
    if doveadm kick "${EMAIL}" 2>/dev/null; then
        KICKED="true"
    fi
fi

onx_audit "onx-mailbox" "password-change email=${EMAIL} kicked=${KICKED}"

onx_json_out \
    "email"         "${EMAIL}" \
    "password_hash" "${PASSWORD_HASH}" \
    "kicked"        "${KICKED}" \
    "updated"       "true"
