import { describe, it, expect } from 'vitest';
import { extractStatusUpdate } from '../src/processor/statusExtractor.js';

describe('StatusExtractor', () => {
    const base = {
        ts_ms: 1700000000000,
        hotel_id: 1001,
        room_id: '8001',
        device_id: 'dev_001',
        direction: '上报',
        cmd_word: '0x36',
        frame_id: 1,
        udp_raw: 'test',
        sys_lock_status: 0,
        device_list: [],
        fault_list: [],
        control_list: []
    };

    it('should return null when payload is null/undefined', () => {
        expect(extractStatusUpdate(null)).toBeNull();
        expect(extractStatusUpdate(undefined)).toBeNull();
    });

    it('should return null when nothing to update (empty lists, no sys_lock)', () => {
        const payload = {
            ...base,
            sys_lock_status: undefined,
            device_list: [],
            fault_list: [],
            control_list: []
        };
        expect(extractStatusUpdate(payload)).toBeNull();
    });

    it('should return update when sys_lock_status is present even with empty lists', () => {
        const result = extractStatusUpdate({
            ...base,
            sys_lock_status: 1
        });
        expect(result).not.toBeNull();
        expect(result.sys_lock_status).toBe(1);
        expect(result.hotel_id).toBe(1001);
        expect(result.room_id).toBe('8001');
        expect(result.device_id).toBe('dev_001');
    });

    it('should build dev_loops from device_list with 9-digit padded keys', () => {
        const result = extractStatusUpdate({
            ...base,
            device_list: [
                { dev_type: 1, dev_addr: 10, dev_loop: 1, dev_data: 100 },
                { dev_type: 1, dev_addr: 11, dev_loop: 2, dev_data: 0 }
            ]
        });

        expect(result).not.toBeNull();
        expect(result.dev_loops).toEqual({
            '001010001': 100,
            '001011002': 0
        });
    });

    it('should build dev_loops from control_list with type_l/type_h values', () => {
        const result = extractStatusUpdate({
            ...base,
            control_list: [
                { dev_type: 1, dev_addr: 10, dev_loop: 1, type_l: 0, type_h: 1 }
            ]
        });

        expect(result).not.toBeNull();
        expect(result.dev_loops).toEqual({
            '001010001': { type_l: 0, type_h: 1 }
        });
    });

    it('should merge device_list and control_list into dev_loops', () => {
        const result = extractStatusUpdate({
            ...base,
            device_list: [
                { dev_type: 1, dev_addr: 10, dev_loop: 1, dev_data: 100 }
            ],
            control_list: [
                { dev_type: 2, dev_addr: 5, dev_loop: 3, type_l: 1, type_h: 2 }
            ]
        });

        expect(result.dev_loops).toEqual({
            '001010001': 100,
            '002005003': { type_l: 1, type_h: 2 }
        });
    });

    it('should build faulty_device_count from fault_list', () => {
        const result = extractStatusUpdate({
            ...base,
            fault_list: [
                { dev_type: 1, dev_addr: 10, dev_loop: 1, error_type: 2, error_data: 5 }
            ]
        });

        expect(result).not.toBeNull();
        expect(result.faulty_device_count).toEqual([
            { dev_type: 1, dev_addr: 10, dev_loop: 1, error_type: 2, error_data: 5 }
        ]);
    });

    it('should return null when identity fields are missing', () => {
        expect(extractStatusUpdate({ ...base, hotel_id: null })).toBeNull();
        expect(extractStatusUpdate({ ...base, room_id: '' })).toBeNull();
        expect(extractStatusUpdate({ ...base, device_id: '' })).toBeNull();
        expect(extractStatusUpdate({ ...base, ts_ms: null })).toBeNull();
    });

    it('should handle large dev_type/addr/loop values with proper zero-padding', () => {
        const result = extractStatusUpdate({
            ...base,
            device_list: [
                { dev_type: 241, dev_addr: 255, dev_loop: 999, dev_data: 42 }
            ]
        });

        expect(result.dev_loops).toEqual({
            '241255999': 42
        });
    });
});
