/**
 * Status Extractor
 * 
 * Extracts a snapshot-style status update from a validated Kafka payload.
 * The output is suitable for upsert into room_status.room_status_moment.
 */

/**
 * Zero-pad a number to 3 digits.
 * @param {number|string} val
 * @returns {string} e.g. 1 -> "001", 23 -> "023"
 */
const pad3 = (val) => String(val).padStart(3, '0');

/**
 * Build a 9-character loop address key from device parameters.
 * Format: {dev_type(3)}{dev_addr(3)}{dev_loop(3)}
 * Example: type=1, addr=23, loop=12 -> "001023012"
 */
const buildLoopKey = (devType, devAddr, devLoop) =>
    `${pad3(devType)}${pad3(devAddr)}${pad3(devLoop)}`;

/**
 * Extract a status update object from a validated Kafka payload.
 * 
 * @param {Object} payload - The parsed and validated Kafka payload
 * @returns {Object|null} Status update object or null if nothing to update
 */
export const extractStatusUpdate = (payload) => {
    if (!payload) return null;

    const {
        hotel_id,
        room_id,
        device_id,
        ts_ms,
        sys_lock_status,
        device_list = [],
        fault_list = [],
        control_list = [],
        direction,
        cmd_word
    } = payload;

    // Must have identity fields
    if (hotel_id == null || !room_id || !device_id || !ts_ms) {
        return null;
    }

    // Build dev_loops from device_list (0x36) or control_list (0x0F)
    let devLoops = null;

    if (device_list.length > 0) {
        devLoops = {};
        for (const dev of device_list) {
            if (dev.dev_type != null && dev.dev_addr != null && dev.dev_loop != null) {
                const key = buildLoopKey(dev.dev_type, dev.dev_addr, dev.dev_loop);
                devLoops[key] = dev.dev_data ?? null;
            }
        }
        if (Object.keys(devLoops).length === 0) devLoops = null;
    }

    if (control_list.length > 0) {
        if (!devLoops) devLoops = {};
        for (const ctrl of control_list) {
            const devLoop = ctrl.dev_loop ?? ctrl.loop;
            if (ctrl.dev_type != null && ctrl.dev_addr != null && devLoop != null) {
                const key = buildLoopKey(ctrl.dev_type, ctrl.dev_addr, devLoop);
                devLoops[key] = { type_l: ctrl.type_l ?? null, type_h: ctrl.type_h ?? null };
            }
        }
        if (Object.keys(devLoops).length === 0) devLoops = null;
    }

    // Build faulty_device_count from fault_list (full replacement)
    let faultyDeviceCount = null;
    if (fault_list.length > 0) {
        faultyDeviceCount = fault_list.map(f => ({
            dev_type: f.dev_type ?? null,
            dev_addr: f.dev_addr ?? null,
            dev_loop: f.dev_loop ?? null,
            error_type: f.error_type ?? null,
            error_data: f.error_data ?? null
        }));
    }

    // If there's absolutely nothing to update, return null
    if (devLoops === null && faultyDeviceCount === null && sys_lock_status == null) {
        return null;
    }

    // Clamp hotel_id to INT2 range (-32768 to 32767) to match production schema
    const validHotelId = (hotel_id >= -32768 && hotel_id <= 32767) ? hotel_id : 0;

    return {
        hotel_id: validHotelId,
        room_id: String(room_id),
        device_id: String(device_id),
        ts_ms,
        sys_lock_status: sys_lock_status ?? null,
        dev_loops: devLoops,
        faulty_device_count: faultyDeviceCount
    };
};
