#include "pressure_decode.h"
xp_status xp_decode(const xp_profile *p, const uint8_t *b, size_t n, bool transport_ok, xp_result *o) {
    if (!o) return XP_ARGUMENT;
    *o = (xp_result){0};
    if (!p || !b) return XP_ARGUMENT;
    if (p->address != 0x58 || (p->protocol_revision != 31 && p->protocol_revision != 33) ||
        p->pmin_pa < -1000000 || p->pmax_pa > 1000000 ||
        p->pmin_pa > 0 || p->pmax_pa < 0 || p->pmax_pa <= p->pmin_pa)
        return XP_PROFILE;
    if (!transport_ok || n != 5) return XP_TRANSPORT;
    uint32_t u = ((uint32_t)b[0] << 16) | ((uint32_t)b[1] << 8) | b[2];
    int32_t raw = (u & 0x800000u) ? (int32_t)u - 16777216 : (int32_t)u;
    int64_t num = (int64_t)raw * ((int64_t)p->pmax_pa - p->pmin_pa);
    /* Range check on exact rational Pa, before millipa rounding. */
    if (num < (int64_t)p->pmin_pa * 2097152 ||
        num > (int64_t)p->pmax_pa * 2097152) return XP_RANGE;
    int64_t m = num * 1000;
    m = m < 0 ? -((-m + 1048576) / 2097152) : (m + 1048576) / 2097152;
    o->raw_signed = raw; o->pressure_millipa = m; o->decoded = true;
    /* pressure alone is never a qualified suction percentage */
    o->suction_valid = false;
    return XP_OK;
}
