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

APP_DIR="/app"
DATA_ROOT="${EPICRISIS_DATA_ROOT:-/data}"
RUNTIME_ROOT="${EPICRISIS_RUNTIME_DIR:-${DATA_ROOT}/runtime}"
LOG_ROOT="${EPICRISIS_LOG_DIR:-${RUNTIME_ROOT}/logs}"
MONGO_DATA_DIR="${MONGO_DATA_DIR:-${DATA_ROOT}/mongodb}"
REDIS_DATA_DIR="${REDIS_DATA_DIR:-${DATA_ROOT}/redis}"
MONGO_PASSWORD_FILE="${MONGO_PASSWORD_FILE:-${RUNTIME_ROOT}/.mongo_app_password}"
MONGO_APP_DATABASE="${MONGO_APP_DATABASE:-${DB_NAME:-Epicrisis}}"
MONGO_APP_USERNAME="${MONGO_APP_USERNAME:-epicrisis_app}"
MONGO_APP_PASSWORD="${MONGO_APP_PASSWORD:-}"
MONGO_APP_FORCE_RESET="${MONGO_APP_FORCE_RESET:-0}"
APP_HOST="${APP_HOST:-0.0.0.0}"
APP_PORT="${APP_PORT:-7000}"
CELERY_LOG_LEVEL="${CELERY_LOG_LEVEL:-INFO}"
CELERY_QUEUES="${CELERY_QUEUES:-batch_jobs,individual_uploads}"
CELERY_CONCURRENCY="${CELERY_CONCURRENCY:-2}"
EPICRISIS_AUTO_MIGRATE="${EPICRISIS_AUTO_MIGRATE:-1}"
EPICRISIS_AUTO_BOOTSTRAP_ADMIN="${EPICRISIS_AUTO_BOOTSTRAP_ADMIN:-1}"
EPICRISIS_AUTO_WARMUP="${EPICRISIS_AUTO_WARMUP:-0}"
EPICRISIS_WARMUP_RESOURCES="${EPICRISIS_WARMUP_RESOURCES:-cie10,cups}"

link_persistent_dir() {
    local source_path="$1"
    local target_path="$2"

    mkdir -p "$(dirname "${source_path}")" "${target_path}"
    if [[ -L "${source_path}" ]]; then
        return
    fi

    if [[ -d "${source_path}" ]]; then
        cp -a "${source_path}/." "${target_path}/" 2>/dev/null || true
        rm -rf "${source_path}"
    elif [[ -f "${source_path}" ]]; then
        cp -a "${source_path}" "${target_path}/" 2>/dev/null || true
        rm -f "${source_path}"
    fi

    ln -s "${target_path}" "${source_path}"
}

prepare_layout() {
    mkdir -p \
        "${MONGO_DATA_DIR}" \
        "${REDIS_DATA_DIR}" \
        "${REDIS_DATA_DIR}/appendonlydir" \
        "${LOG_ROOT}" \
        "${RUNTIME_ROOT}/_batch_uploads" \
        "${RUNTIME_ROOT}/_batch_extracted" \
        "${RUNTIME_ROOT}/_batch_reports" \
        "${RUNTIME_ROOT}/_individual_uploads" \
        "${RUNTIME_ROOT}/faiss_principal_jerarquico" \
        "${RUNTIME_ROOT}/cups_faiss" \
        "${RUNTIME_ROOT}/soat_faiss" \
        /var/log/epicrisis \
        /var/run/epicrisis

    link_persistent_dir "${APP_DIR}/logs" "${LOG_ROOT}"
    link_persistent_dir "${APP_DIR}/_batch_uploads" "${RUNTIME_ROOT}/_batch_uploads"
    link_persistent_dir "${APP_DIR}/_batch_extracted" "${RUNTIME_ROOT}/_batch_extracted"
    link_persistent_dir "${APP_DIR}/_batch_reports" "${RUNTIME_ROOT}/_batch_reports"
    link_persistent_dir "${APP_DIR}/_individual_uploads" "${RUNTIME_ROOT}/_individual_uploads"
    link_persistent_dir "${APP_DIR}/faiss_principal_jerarquico" "${RUNTIME_ROOT}/faiss_principal_jerarquico"
    link_persistent_dir "${APP_DIR}/cups_faiss" "${RUNTIME_ROOT}/cups_faiss"
    link_persistent_dir "${APP_DIR}/soat_faiss" "${RUNTIME_ROOT}/soat_faiss"

    touch "${LOG_ROOT}/audit.jsonl"
    chown -R epicrisis:epicrisis \
        "${MONGO_DATA_DIR}" \
        "${REDIS_DATA_DIR}" \
        "${LOG_ROOT}" \
        "${RUNTIME_ROOT}" \
        /var/log/epicrisis \
        /var/run/epicrisis
    chmod 750 "${MONGO_DATA_DIR}" "${REDIS_DATA_DIR}"
    chmod 750 "${REDIS_DATA_DIR}/appendonlydir"
}

persist_mongo_password() {
    if [[ -z "${MONGO_APP_PASSWORD}" ]]; then
        echo "No se pudo resolver MONGO_APP_PASSWORD para el contenedor all-in-one." >&2
        exit 1
    fi

    if [[ ! -f "${MONGO_PASSWORD_FILE}" ]] || [[ "$(tr -d '\r\n' < "${MONGO_PASSWORD_FILE}")" != "${MONGO_APP_PASSWORD}" ]]; then
        printf '%s' "${MONGO_APP_PASSWORD}" > "${MONGO_PASSWORD_FILE}"
    fi

    chmod 600 "${MONGO_PASSWORD_FILE}"
    chown epicrisis:epicrisis "${MONGO_PASSWORD_FILE}"
}

resolve_mongo_password() {
    if [[ -n "${MONGO_APP_PASSWORD}" ]]; then
        persist_mongo_password
        echo "Usando MONGO_APP_PASSWORD provisto por entorno."
        return
    fi

    if [[ -f "${MONGO_PASSWORD_FILE}" ]]; then
        MONGO_APP_PASSWORD="$(tr -d '\r\n' < "${MONGO_PASSWORD_FILE}")"
        if [[ -n "${MONGO_APP_PASSWORD}" ]]; then
            echo "Usando MONGO_APP_PASSWORD persistido en ${MONGO_PASSWORD_FILE}."
            persist_mongo_password
            return
        fi
    fi

    MONGO_APP_PASSWORD="$(
        python - <<'PY'
import secrets
print(secrets.token_urlsafe(24))
PY
    )"
    echo "MONGO_APP_PASSWORD no estaba definido; se generó una clave interna persistente."
    persist_mongo_password
}

export_runtime_env() {
    export DB_NAME="${DB_NAME:-${MONGO_APP_DATABASE}}"
    export COLLECTION_NAME="${COLLECTION_NAME:-HistoriaClinica}"
    export REDIS_URL="${REDIS_URL:-redis://127.0.0.1:6379/0}"
    export BATCH_DISPATCHER="${BATCH_DISPATCHER:-celery}"
    export APP_HOST
    export APP_PORT
    export CELERY_LOG_LEVEL
    export CELERY_QUEUES
    export CELERY_CONCURRENCY
    export MONGO_APP_DATABASE
    export MONGO_APP_USERNAME
    export MONGO_APP_PASSWORD
    export MONGO_APP_FORCE_RESET

    if [[ -z "${MONGO_URI:-}" ]]; then
        export MONGO_URI="mongodb://${MONGO_APP_USERNAME}:${MONGO_APP_PASSWORD}@127.0.0.1:27017/${DB_NAME}?authSource=${MONGO_APP_DATABASE}"
    fi

    if [[ -z "${AUDIT_LOG_FILE:-}" ]]; then
        export AUDIT_LOG_FILE="logs/audit.jsonl"
    fi
}

wait_for_mongo() {
    local retries="${1:-30}"
    local sleep_seconds="${2:-2}"
    local attempt

    for ((attempt = 1; attempt <= retries; attempt += 1)); do
        if gosu epicrisis mongosh --quiet --host 127.0.0.1 --port 27017 --eval "db.adminCommand({ ping: 1 }).ok" >/dev/null 2>&1; then
            return 0
        fi
        sleep "${sleep_seconds}"
    done

    echo "MongoDB no respondió durante la inicialización." >&2
    return 1
}

start_temp_mongo() {
    gosu epicrisis mongod \
        --bind_ip 127.0.0.1 \
        --port 27017 \
        --dbpath "${MONGO_DATA_DIR}" \
        --fork \
        --logpath /var/log/epicrisis/mongod-init.log \
        --setParameter diagnosticDataCollectionEnabled=false
}

stop_temp_mongo() {
    gosu epicrisis mongod --dbpath "${MONGO_DATA_DIR}" --shutdown || true
}

ensure_mongo_user() {
    gosu epicrisis env \
        MONGO_APP_DATABASE="${MONGO_APP_DATABASE}" \
        MONGO_APP_USERNAME="${MONGO_APP_USERNAME}" \
        MONGO_APP_PASSWORD="${MONGO_APP_PASSWORD}" \
        MONGO_APP_FORCE_RESET="${MONGO_APP_FORCE_RESET}" \
        mongosh --quiet --host 127.0.0.1 --port 27017 --eval '
            const dbName = process.env.MONGO_APP_DATABASE;
            const username = process.env.MONGO_APP_USERNAME;
            const password = process.env.MONGO_APP_PASSWORD;
            const forceReset = ["1", "true", "yes", "on"].includes((process.env.MONGO_APP_FORCE_RESET || "").toLowerCase());
            const appDb = db.getSiblingDB(dbName);
            const roles = [
              { role: "readWrite", db: dbName },
              { role: "dbAdmin", db: dbName }
            ];
            const existing = appDb.getUser(username);
            if (!existing) {
              appDb.createUser({ user: username, pwd: password, roles });
              print(`Mongo user created: ${username}`);
            } else if (forceReset) {
              appDb.updateUser(username, { pwd: password, roles });
              print(`Mongo user password updated: ${username}`);
            } else {
              print(`Mongo user already exists: ${username}`);
            }
        '
}

run_runtime_bootstrap() {
    local bootstrap_mongo_uri="mongodb://127.0.0.1:27017/${DB_NAME}"

    if [[ "${EPICRISIS_AUTO_MIGRATE}" == "1" ]]; then
        gosu epicrisis env MONGO_URI="${bootstrap_mongo_uri}" /app/.venv/bin/python -m app.migrations.run
    fi

    if [[ "${EPICRISIS_AUTO_BOOTSTRAP_ADMIN}" == "1" ]]; then
        gosu epicrisis env MONGO_URI="${bootstrap_mongo_uri}" /app/.venv/bin/python -m app.scripts.bootstrap_admin
    fi

    if [[ "${EPICRISIS_AUTO_WARMUP}" == "1" ]]; then
        local args=()
        local resource
        IFS=',' read -r -a resources <<<"${EPICRISIS_WARMUP_RESOURCES}"
        for resource in "${resources[@]}"; do
            resource="$(echo "${resource}" | xargs)"
            if [[ -n "${resource}" ]]; then
                args+=(--resource "${resource}")
            fi
        done
        if [[ "${#args[@]}" -gt 0 ]]; then
            gosu epicrisis env MONGO_URI="${bootstrap_mongo_uri}" /app/.venv/bin/python -m app.scripts.warmup_resources "${args[@]}"
        fi
    fi
}

main() {
    prepare_layout
    resolve_mongo_password
    export_runtime_env
    start_temp_mongo
    trap stop_temp_mongo EXIT
    wait_for_mongo
    ensure_mongo_user
    run_runtime_bootstrap
    stop_temp_mongo
    trap - EXIT

    exec /usr/bin/supervisord -c /etc/supervisor/conf.d/epicrisis.conf
}

main "$@"
