#ifndef LAMP_UI_DISPATCH_H
#define LAMP_UI_DISPATCH_H

#include "lamp_ui_policy.h"

typedef enum {
    LUID_ACK_ACCEPTED,
    LUID_ACK_NOT_READY,
    LUID_ACK_INVALID_COMMAND,
    LUID_ACK_BAD_SESSION,
    LUID_ACK_STALE_SEQUENCE,
    LUID_ACK_SEQUENCE_COLLISION
} lamp_ui_ack_status;

typedef struct {
    uint64_t session_id;
    uint32_t sequence;
    lamp_ui_button button;
} lamp_ui_event;

typedef struct {
    uint32_t sequence;
    lamp_ui_ack_status status;
    lg_mode selected_mode;
    bool running;
    uint32_t remaining_ms;
    bool duplicate;
} lamp_ui_ack;

typedef struct {
    lg_guard *guard;
    uint64_t session_id;
    uint32_t last_sequence;
    lamp_ui_button last_button;
    lamp_ui_ack last_ack;
    lg_mode selected_mode;
    bool sequence_seen;
} lamp_ui_dispatcher;

/* The session must be allocated by the target boot/session layer and be
   nonzero. selected_mode is the last acknowledged UI mode; the guard remains
   authoritative for faults, active timing and all physical-output decisions. */
bool lamp_ui_dispatcher_init(lamp_ui_dispatcher *dispatcher, lg_guard *guard,
                             uint64_t session_id, lg_mode selected_mode);

/* Dispatch a decoded SoC/UI event. Fresh sequence numbers are consumed even
   when a valid-session event is rejected. Exact retries return a live status
   snapshot without repeating stop/arm side effects. This is not a wire parser. */
bool lamp_ui_dispatcher_handle(lamp_ui_dispatcher *dispatcher,
                              const lamp_ui_event *event, uint32_t now_ms,
                              lamp_ui_ack *ack);

#endif
