/*
 * ==================================================================================
 * State Machine Header - Protocol State Management
 *
 * ISA Project
 * Author: Roman Necas (xnecasr00)
 * Date: 13. October 2025
 *
 * PURPOSE:
 * This header defines the state machine layer for the ICMP covert channel file
 * transfer protocol. It implements separate state machines for client and server
 * modes, providing structured protocol flow control, timeout handling, and error
 * recovery.
 *
 * RESPONSIBILITIES:
 * - Client state machine: Manages file transmission states (START → DATA → END)
 * - Server state machine: Manages file reception states (LISTENING → RECEIVING → CLOSING)
 * - State transition validation: Ensures only valid state changes occur
 * - Timeout detection: Detects idle sessions and triggers retransmissions
 * - Retry logic with exponential backoff: Prevents network flooding
 * - Error recovery: Handles recoverable errors vs fatal errors
 * - Statistics tracking: Monitors state duration, retry counts, etc.
 *
 * STATE MACHINE PATTERN:
 * Both client and server use event-driven state machines:
 * - Current state: Represents current protocol phase
 * - Events: Triggers for state transitions (packet received, timeout, error)
 * - Transitions: Valid state changes defined by protocol
 * - Actions: Side effects when entering/exiting states
 *
 * CLIENT STATE MACHINE:
 * Manages the file sending protocol:
 *   IDLE → START_SENT → DATA_TRANSFER ⇄ DATA_WAIT_ACK → END_SENT → COMPLETED
 *   Any state can transition to ERROR or ABORT on failure
 *
 * SERVER STATE MACHINE:
 * Manages the file receiving protocol:
 *   LISTENING → SESSION_INIT → RECEIVING_DATA ⇄ DATA_ACK_SENT → SESSION_CLOSING → COMPLETED
 *   Any state can transition to ERROR or TIMEOUT on failure
 *
 * TIMEOUT HANDLING:
 * - Client timeouts trigger retransmissions with exponential backoff
 * - Server timeouts indicate client failure or network partition
 * - Timeout values increase: 2s → 4s → 8s → 16s → 30s (capped)
 * ==================================================================================
 */

#ifndef STATE_MACHINE_H
#define STATE_MACHINE_H

#include <time.h>
#include <stdint.h>

/*
 * ==================================================================================
 * CLIENT STATES
 * ==================================================================================
 */

/*
 * client_state_t - Client-side protocol states
 *
 * These states represent the phases of file transmission from client to server.
 * The client progresses through these states sequentially, with possible loops
 * between DATA_TRANSFER and DATA_WAIT_ACK for each chunk.
 *
 * STATE DIAGRAM:
 *
 *   IDLE
 *    ↓
 *   START_SENT ──────┐
 *    ↓               │ (timeout/retry)
 *   DATA_TRANSFER    │
 *    ↓               │
 *   DATA_WAIT_ACK ───┘
 *    ↓ (ACK received)
 *   [Loop back to DATA_TRANSFER if more chunks]
 *    ↓ (all chunks sent)
 *   END_SENT ────────┐
 *    ↓               │ (timeout/retry)
 *   COMPLETED        │
 *                    ↓
 *   ERROR/ABORT (from any state on failure)
 */
typedef enum {
    /*
     * CLIENT_IDLE - Initial state before transfer begins
     *
     * Entry: When client_sm_init() is called
     * Exit: When file is opened and ready to send
     * Next: CLIENT_START_SENT
     *
     * Activities in this state:
     * - Open file for reading
     * - Generate session ID
     * - Prepare metadata (filename, file size, IV, salt)
     */
    CLIENT_IDLE,

    /*
     * CLIENT_START_SENT - START packet sent, waiting for ACK
     *
     * Entry: After sending START packet with file metadata
     * Exit: When START-ACK received or timeout/max retries
     * Next: CLIENT_DATA_TRANSFER (success), CLIENT_ERROR (failure)
     *
     * Activities in this state:
     * - Wait for START-ACK from server
     * - Retry sending START on timeout (with exponential backoff)
     * - Check retry count against MAX_RETRIES
     *
     * Timeout behavior: Retry up to MAX_RETRIES times before failing
     */
    CLIENT_START_SENT,

    /*
     * CLIENT_DATA_TRANSFER - Sending DATA packet
     *
     * Entry: After START-ACK received, or after previous DATA-ACK
     * Exit: After DATA packet sent
     * Next: CLIENT_DATA_WAIT_ACK
     *
     * Activities in this state:
     * - Read next chunk from file
     * - Encrypt chunk
     * - Create DATA packet with IFTP header
     * - Send DATA packet
     * - Increment sequence number
     */
    CLIENT_DATA_TRANSFER,

    /*
     * CLIENT_DATA_WAIT_ACK - Waiting for ACK after DATA packet
     *
     * Entry: After DATA packet sent
     * Exit: When DATA-ACK received, NACK received, or timeout
     * Next: CLIENT_DATA_TRANSFER (more chunks), CLIENT_END_SENT (all sent),
     *       CLIENT_DATA_WAIT_ACK (retry on timeout)
     *
     * Activities in this state:
     * - Wait for ACK matching current sequence number
     * - Retry sending DATA on timeout (with exponential backoff)
     * - Check retry count against MAX_RETRIES
     * - Check if more chunks remain to send
     *
     * Timeout behavior: Retry same DATA packet up to MAX_RETRIES times
     * NACK handling: Resend DATA immediately (counts as retry)
     */
    CLIENT_DATA_WAIT_ACK,

    /*
     * CLIENT_END_SENT - END packet sent, waiting for final ACK
     *
     * Entry: After all DATA packets acknowledged
     * Exit: When END-ACK received or timeout/max retries
     * Next: CLIENT_COMPLETED (success), CLIENT_ERROR (failure)
     *
     * Activities in this state:
     * - Wait for END-ACK from server
     * - Retry sending END on timeout
     * - Check retry count against MAX_RETRIES
     *
     * Timeout behavior: Retry up to MAX_RETRIES times before failing
     */
    CLIENT_END_SENT,

    /*
     * CLIENT_COMPLETED - Transfer completed successfully
     *
     * Entry: After END-ACK received
     * Exit: None (terminal state)
     * Next: None
     *
     * Activities in this state:
     * - Close file
     * - Print transfer statistics
     * - Clean up resources
     *
     * This is a terminal success state.
     */
    CLIENT_COMPLETED,

    /*
     * CLIENT_ERROR - Transfer failed due to error
     *
     * Entry: From any state on unrecoverable error
     * Exit: None (terminal state)
     * Next: None
     *
     * Causes:
     * - Max retries exceeded (MAX_RETRIES = 5)
     * - File I/O error (disk read failure)
     * - Network error (cannot send packets)
     * - Protocol error (invalid packet from server)
     *
     * This is a terminal failure state.
     */
    CLIENT_ERROR,

    /*
     * CLIENT_ABORT - Transfer aborted by user
     *
     * Entry: From any state on user interrupt (SIGINT)
     * Exit: None (terminal state)
     * Next: None
     *
     * Causes:
     * - User presses Ctrl+C
     * - User sends SIGTERM
     * - Application shutdown requested
     *
     * This is a terminal state, resources should be cleaned up gracefully.
     */
    CLIENT_ABORT
} client_state_t;

/*
 * ==================================================================================
 * SERVER STATES
 * ==================================================================================
 */

/*
 * server_state_t - Server-side protocol states
 *
 * These states represent the phases of file reception from client.
 * The server remains in LISTENING until a START packet arrives, then
 * progresses through reception states.
 *
 * STATE DIAGRAM:
 *
 *   LISTENING
 *    ↓ (START received)
 *   SESSION_INIT
 *    ↓ (START-ACK sent)
 *   RECEIVING_DATA
 *    ↓ (DATA received)
 *   DATA_ACK_SENT
 *    ↓ (more DATA expected)
 *   RECEIVING_DATA ──┐
 *    ↓               │ (loop for each DATA packet)
 *   DATA_ACK_SENT ───┘
 *    ↓ (END received)
 *   SESSION_CLOSING
 *    ↓ (END-ACK sent)
 *   COMPLETED
 *
 *   ERROR/TIMEOUT (from any state on failure)
 */
typedef enum {
    /*
     * SERVER_LISTENING - Waiting for START packet from any client
     *
     * Entry: When server_sm_init() is called, or after previous session completes
     * Exit: When valid START packet received
     * Next: SERVER_SESSION_INIT
     *
     * Activities in this state:
     * - Poll for incoming ICMP packets (non-blocking)
     * - Validate packet magic number (0xDEADBEEF)
     * - Check packet type (must be START)
     * - Extract metadata from START packet
     *
     * Timeout: No timeout in this state (server waits indefinitely)
     */
    SERVER_LISTENING,

    /*
     * SERVER_SESSION_INIT - New session initialized, sending START-ACK
     *
     * Entry: After valid START packet received
     * Exit: After START-ACK sent
     * Next: SERVER_RECEIVING_DATA
     *
     * Activities in this state:
     * - Create new server session structure
     * - Extract metadata (filename, file_size, IV, salt)
     * - Open output file (basename only for security)
     * - Initialize crypto engine for decryption
     * - Send START-ACK to client
     * - Set expected_seq to 0 for first DATA packet
     *
     * Error handling: Transition to SERVER_ERROR if file cannot be created
     */
    SERVER_SESSION_INIT,

    /*
     * SERVER_RECEIVING_DATA - Waiting for DATA packet
     *
     * Entry: After START-ACK sent, or after previous DATA-ACK sent
     * Exit: When valid DATA packet received or timeout
     * Next: SERVER_DATA_ACK_SENT (DATA received), SERVER_TIMEOUT (timeout)
     *
     * Activities in this state:
     * - Wait for DATA packet with expected sequence number
     * - Validate sequence number (must match expected_seq)
     * - Validate CRC32 checksum
     * - Decrypt data chunk
     * - Write chunk to file
     *
     * Timeout: If no packet received within idle_timeout (default 30s),
     *          transition to SERVER_TIMEOUT
     */
    SERVER_RECEIVING_DATA,

    /*
     * SERVER_DATA_ACK_SENT - ACK sent for received DATA packet
     *
     * Entry: After valid DATA packet received and written
     * Exit: Immediately after ACK sent
     * Next: SERVER_RECEIVING_DATA (more DATA expected),
     *       SERVER_SESSION_CLOSING (END packet received)
     *
     * Activities in this state:
     * - Send DATA-ACK with acknowledged sequence number
     * - Increment expected_seq for next DATA packet
     * - Update transfer statistics
     *
     * This is a transient state - transitions immediately to RECEIVING_DATA
     */
    SERVER_DATA_ACK_SENT,

    /*
     * SERVER_SESSION_CLOSING - END packet received, sending final ACK
     *
     * Entry: After valid END packet received
     * Exit: After END-ACK sent
     * Next: SERVER_COMPLETED
     *
     * Activities in this state:
     * - Verify all expected data received (bytes_written == file_size)
     * - Finalize file (close handle)
     * - Send END-ACK to client
     * - Clean up session resources
     */
    SERVER_SESSION_CLOSING,

    /*
     * SERVER_COMPLETED - Session completed successfully
     *
     * Entry: After END-ACK sent
     * Exit: None (terminal state for this session)
     * Next: SERVER_LISTENING (for next session)
     *
     * Activities in this state:
     * - Print transfer statistics
     * - Clean up crypto resources
     * - Reset to LISTENING for next client
     *
     * This is a terminal success state for the current session.
     * Server can return to LISTENING to handle next client.
     */
    SERVER_COMPLETED,

    /*
     * SERVER_ERROR - Session failed due to error
     *
     * Entry: From any state on unrecoverable error
     * Exit: None (terminal state for this session)
     * Next: SERVER_LISTENING (after cleanup)
     *
     * Causes:
     * - File write error (disk full, permissions)
     * - Decryption failure (wrong key, corrupted data)
     * - Protocol violation (invalid packet, wrong session ID)
     * - Checksum mismatch (data corruption)
     *
     * This is a terminal failure state. Server should clean up and return
     * to LISTENING for next client.
     */
    SERVER_ERROR,

    /*
     * SERVER_TIMEOUT - Session timed out waiting for client
     *
     * Entry: From RECEIVING_DATA when idle_timeout exceeded
     * Exit: None (terminal state for this session)
     * Next: SERVER_LISTENING (after cleanup)
     *
     * Causes:
     * - Client crashed or network disconnected
     * - Client waiting for ACK that was lost
     * - Network partition
     *
     * Server should clean up incomplete file and return to LISTENING.
     */
    SERVER_TIMEOUT
} server_state_t;

/*
 * ==================================================================================
 * PROTOCOL EVENTS
 * ==================================================================================
 */

/*
 * protocol_event_t - Events that trigger state machine transitions
 *
 * These events are generated by the protocol engine based on network activity,
 * timeouts, file I/O results, and user actions.
 */
typedef enum {
    /*
     * EVENT_TIMEOUT - Timeout occurred waiting for response
     *
     * Client: Triggers retry of last packet sent (START, DATA, or END)
     * Server: Triggers transition to SERVER_TIMEOUT if in RECEIVING_DATA
     *
     * Event data: NULL
     */
    EVENT_TIMEOUT,

    /*
     * EVENT_PACKET_RECEIVED - Valid packet received from peer
     *
     * Client: START-ACK, DATA-ACK, or END-ACK received
     * Server: START, DATA, or END packet received
     *
     * Event data: Pointer to received packet (iftp_header_t*)
     */
    EVENT_PACKET_RECEIVED,

    /*
     * EVENT_PACKET_SENT - Packet successfully sent to peer
     *
     * Client: START, DATA, or END packet sent
     * Server: ACK packet sent
     *
     * Event data: Pointer to sent packet (iftp_header_t*)
     */
    EVENT_PACKET_SENT,

    /*
     * EVENT_ACK_RECEIVED - ACK packet received matching expected sequence
     *
     * Client: Triggers transition from WAIT_ACK to next state
     * Server: Not used
     *
     * Event data: Pointer to ACK packet (iftp_header_t*)
     */
    EVENT_ACK_RECEIVED,

    /*
     * EVENT_ERROR - Unrecoverable error occurred
     *
     * Triggers transition to ERROR state from any state.
     *
     * Event data: Pointer to error code (error_code_t*)
     */
    EVENT_ERROR,

    /*
     * EVENT_FILE_EOF - End of file reached during read
     *
     * Client: All chunks sent, transition to END_SENT
     * Server: Not used
     *
     * Event data: NULL
     */
    EVENT_FILE_EOF,

    /*
     * EVENT_USER_ABORT - User requested abort (Ctrl+C, SIGTERM)
     *
     * Triggers transition to ABORT state from any state.
     *
     * Event data: NULL
     */
    EVENT_USER_ABORT,

    /*
     * EVENT_RETRY_EXCEEDED - Maximum retry count exceeded
     *
     * Triggers transition to ERROR state when retries exhausted.
     *
     * Event data: NULL
     */
    EVENT_RETRY_EXCEEDED
} protocol_event_t;

/*
 * ==================================================================================
 * CLIENT STATE MACHINE STRUCTURE
 * ==================================================================================
 */

/*
 * client_state_machine_t - Client state tracking and control
 *
 * This structure maintains all state for the client-side protocol engine.
 * It tracks the current protocol phase, retry logic, sequence numbers, and
 * timing information.
 *
 * LIFECYCLE:
 * 1. Initialized by client_sm_init()
 * 2. Transitions managed by client_sm_transition()
 * 3. Timeouts checked by client_sm_check_timeout()
 * 4. Events handled by client_sm_handle_event()
 * 5. Reset by client_sm_reset() if retry needed
 */
typedef struct {
    /*
     * current_state - Current protocol state
     *
     * One of the client_state_t enum values.
     * Modified by client_sm_transition() only.
     */
    client_state_t current_state;

    /*
     * previous_state - Previous state before current
     *
     * Used for error recovery and debugging.
     * Can transition back to previous_state if error is recoverable.
     */
    client_state_t previous_state;

    /*
     * current_seq - Current sequence number for packets
     *
     * Incremented after each DATA packet sent.
     * Used in IFTP header seq_num field.
     * Range: 0 to UINT32_MAX (wraps around)
     *
     * Sequence number lifecycle:
     * - START packet: seq_num = 0
     * - DATA packet 1: seq_num = 1
     * - DATA packet 2: seq_num = 2
     * - ...
     * - END packet: seq_num = (last DATA seq_num + 1)
     */
    uint32_t current_seq;

    /*
     * ack_expected - Expected sequence number in ACK response
     *
     * When waiting for ACK, this holds the sequence number we expect
     * to see in the ACK packet. Must match current_seq.
     */
    uint32_t ack_expected;

    /*
     * retry_count - Number of retries attempted for current packet
     *
     * Incremented each time a timeout occurs and packet is resent.
     * Reset to 0 when ACK received.
     * Compared against MAX_RETRIES (5) to detect failure.
     *
     * If retry_count >= MAX_RETRIES:
     *   - Generate EVENT_RETRY_EXCEEDED
     *   - Transition to CLIENT_ERROR
     */
    uint32_t retry_count;

    /*
     * state_entry_time - When current state was entered (Unix timestamp)
     *
     * Set by client_sm_transition() using time(NULL).
     * Used to calculate:
     * - Time spent in current state: time(NULL) - state_entry_time
     * - State duration statistics
     */
    time_t state_entry_time;

    /*
     * last_activity - Last time any network activity occurred
     *
     * Updated when:
     * - Packet sent
     * - Packet received
     *
     * Used to detect idle sessions and calculate overall session duration.
     */
    time_t last_activity;

    /*
     * timeout_seconds - Timeout duration for current state
     *
     * How long to wait before considering state timed out.
     * Compared against: time(NULL) - state_entry_time
     *
     * Exponential backoff:
     * - Retry 0: 2 seconds  (INITIAL_TIMEOUT)
     * - Retry 1: 4 seconds
     * - Retry 2: 8 seconds
     * - Retry 3: 16 seconds
     * - Retry 4: 30 seconds (MAX_TIMEOUT)
     * - Retry 5: Fail (MAX_RETRIES exceeded)
     *
     * Formula: timeout = min(INITIAL_TIMEOUT * (2 ^ retry_count), MAX_TIMEOUT)
     */
    int timeout_seconds;

    /*
     * session_id - Unique session identifier (16-bit)
     *
     * Generated by client_sm_init() using utils_generate_session_id()
     * (cryptographically secure random number).
     *
     * Used in all IFTP packets to distinguish this transfer from others.
     * Server uses this to track which session a packet belongs to.
     */
    uint16_t session_id;
} client_state_machine_t;

/*
 * ==================================================================================
 * SERVER STATE MACHINE STRUCTURE
 * ==================================================================================
 */

/*
 * server_state_machine_t - Server state tracking and control
 *
 * This structure maintains all state for the server-side protocol engine.
 * It tracks the current reception phase, expected sequence numbers, and
 * session timeout information.
 *
 * LIFECYCLE:
 * 1. Initialized by server_sm_init()
 * 2. Transitions managed by server_sm_transition()
 * 3. Timeouts checked by server_sm_check_timeout()
 * 4. Events handled by server_sm_handle_event()
 * 5. Reset by server_sm_reset() after session completes
 */
typedef struct {
    /*
     * current_state - Current protocol state
     *
     * One of the server_state_t enum values.
     * Modified by server_sm_transition() only.
     */
    server_state_t current_state;

    /*
     * previous_state - Previous state before current
     *
     * Used for debugging and state transition validation.
     */
    server_state_t previous_state;

    /*
     * expected_seq - Expected sequence number in next DATA packet
     *
     * Initialized to 0 when START packet received.
     * Incremented after each valid DATA packet.
     *
     * Used to:
     * - Validate received DATA packet has correct seq_num
     * - Detect duplicate packets (seq_num < expected_seq)
     * - Detect skipped packets (seq_num > expected_seq)
     */
    uint32_t expected_seq;

    /*
     * last_ack_sent - Sequence number of last ACK sent
     *
     * Used to detect:
     * - Duplicate ACKs (can happen if client didn't receive ACK)
     * - ACK retransmission needed
     */
    uint32_t last_ack_sent;

    /*
     * state_entry_time - When current state was entered
     *
     * Set by server_sm_transition() using time(NULL).
     * Used to calculate time spent in current state.
     */
    time_t state_entry_time;

    /*
     * last_activity - Last time packet received from client
     *
     * Updated when valid packet received from client.
     * Used to detect client failure:
     *   If (time(NULL) - last_activity) > idle_timeout:
     *     Transition to SERVER_TIMEOUT
     */
    time_t last_activity;

    /*
     * idle_timeout - Maximum idle time before timeout (seconds)
     *
     * Default: SESSION_TIMEOUT (30 seconds)
     *
     * If no packet received from client within this time, assume:
     * - Client crashed
     * - Network partition
     * - All retries exhausted on client side
     *
     * Server transitions to SERVER_TIMEOUT and cleans up session.
     */
    int idle_timeout;

    /*
     * session_id - Session identifier from client
     *
     * Extracted from START packet.
     * Used to validate that DATA/END packets belong to this session.
     *
     * Packets with different session_id are ignored or trigger
     * new session creation (if in LISTENING state).
     */
    uint16_t session_id;
} server_state_machine_t;

/*
 * ==================================================================================
 * CORE STATE MACHINE FUNCTIONS
 * ==================================================================================
 */

/*
 * client_sm_init - Initialize client state machine
 *
 * Sets up initial state for new file transfer session:
 * - current_state = CLIENT_IDLE
 * - current_seq = 0
 * - retry_count = 0
 * - timeout_seconds = INITIAL_TIMEOUT (2)
 * - Generates session_id using utils_generate_session_id()
 *
 * @param sm: State machine structure to initialize
 * @param session_id: Session ID to use (0 = generate new ID)
 */
void client_sm_init(client_state_machine_t *sm, uint16_t session_id);

/*
 * server_sm_init - Initialize server state machine
 *
 * Sets up initial state for server listening mode:
 * - current_state = SERVER_LISTENING
 * - expected_seq = 0
 * - idle_timeout = SESSION_TIMEOUT (30)
 *
 * @param sm: State machine structure to initialize
 */
void server_sm_init(server_state_machine_t *sm);

/*
 * client_sm_transition - Transition client to new state
 *
 * Validates transition is legal, updates state, and records timing information.
 *
 * @param sm: Client state machine
 * @param new_state: Desired next state
 * @param reason: Human-readable transition reason (for debugging)
 * @return: 0 on success, -1 if transition invalid
 */
int client_sm_transition(client_state_machine_t *sm, client_state_t new_state, const char *reason);

/*
 * server_sm_transition - Transition server to new state
 *
 * Validates transition is legal, updates state, and records timing information.
 *
 * @param sm: Server state machine
 * @param new_state: Desired next state
 * @param reason: Human-readable transition reason (for debugging)
 * @return: 0 on success, -1 if transition invalid
 */
int server_sm_transition(server_state_machine_t *sm, server_state_t new_state, const char *reason);

/*
 * client_sm_check_timeout - Check if client state has timed out
 *
 * Compares (current_time - state_entry_time) against timeout_seconds.
 *
 * @param sm: Client state machine
 * @return: 1 if timed out, 0 if not timed out
 */
int client_sm_check_timeout(client_state_machine_t *sm);

/*
 * server_sm_check_timeout - Check if server session has timed out
 *
 * Compares (current_time - last_activity) against idle_timeout.
 *
 * @param sm: Server state machine
 * @return: 1 if timed out, 0 if not timed out
 */
int server_sm_check_timeout(server_state_machine_t *sm);

/*
 * client_sm_handle_event - Process event and transition accordingly
 *
 * Event-driven state machine update:
 * - Validates event is valid for current state
 * - Performs appropriate transition
 * - Updates sequence numbers, retry counts
 *
 * @param sm: Client state machine
 * @param event: Event that occurred
 * @param event_data: Event-specific data (packet, error code, etc.)
 * @return: 0 on success, -1 on error
 */
int client_sm_handle_event(client_state_machine_t *sm, protocol_event_t event, void *event_data);

/*
 * server_sm_handle_event - Process event and transition accordingly
 *
 * @param sm: Server state machine
 * @param event: Event that occurred
 * @param event_data: Event-specific data
 * @return: 0 on success, -1 on error
 */
int server_sm_handle_event(server_state_machine_t *sm, protocol_event_t event, void *event_data);

/*
 * ==================================================================================
 * UTILITY FUNCTIONS
 * ==================================================================================
 */

/*
 * client_state_name - Get human-readable name for client state
 * @return: String name like "CLIENT_IDLE", "CLIENT_DATA_TRANSFER", etc.
 */
const char *client_state_name(client_state_t state);

/*
 * server_state_name - Get human-readable name for server state
 * @return: String name like "SERVER_LISTENING", "SERVER_RECEIVING_DATA", etc.
 */
const char *server_state_name(server_state_t state);

/*
 * event_name - Get human-readable name for protocol event
 * @return: String name like "EVENT_TIMEOUT", "EVENT_ACK_RECEIVED", etc.
 */
const char *event_name(protocol_event_t event);

/*
 * ==================================================================================
 * ENHANCED STATE MACHINE FUNCTIONS
 * ==================================================================================
 */

/*
 * client_sm_is_valid_transition - Check if state transition is valid
 *
 * Validates state machine invariants. Prevents illegal transitions like:
 * - CLIENT_IDLE → CLIENT_END_SENT (skipping DATA phase)
 * - CLIENT_COMPLETED → CLIENT_DATA_TRANSFER (no restart from completed)
 *
 * @return: 1 if transition valid, 0 if invalid
 */
int client_sm_is_valid_transition(client_state_t current, client_state_t next);

/*
 * server_sm_is_valid_transition - Check if state transition is valid
 * @return: 1 if transition valid, 0 if invalid
 */
int server_sm_is_valid_transition(server_state_t current, server_state_t next);

/*
 * client_sm_can_recover - Check if error is recoverable
 *
 * Determines if client can retry after error:
 * - retry_count < MAX_RETRIES: recoverable
 * - retry_count >= MAX_RETRIES: not recoverable
 *
 * @return: 1 if can recover, 0 if cannot
 */
int client_sm_can_recover(const client_state_machine_t *sm);

/*
 * server_sm_can_recover - Check if server error is recoverable
 * @return: 1 if can recover, 0 if cannot
 */
int server_sm_can_recover(const server_state_machine_t *sm);

/*
 * client_sm_reset - Reset state machine for retry
 *
 * Resets to IDLE state while preserving session_id.
 * Used for retry after recoverable error.
 */
void client_sm_reset(client_state_machine_t *sm);

/*
 * server_sm_reset - Reset state machine to LISTENING
 *
 * Used after session completion or error to prepare for next client.
 */
void server_sm_reset(server_state_machine_t *sm);

/*
 * client_sm_handle_timeout_with_backoff - Handle timeout with exponential backoff
 *
 * Increments retry_count and calculates new timeout:
 *   timeout = min(INITIAL_TIMEOUT * (2 ^ retry_count), MAX_TIMEOUT)
 *
 * @return: 0 if retry possible, -1 if max retries exceeded
 */
int client_sm_handle_timeout_with_backoff(client_state_machine_t *sm);

/*
 * client_sm_get_statistics - Get state machine statistics
 *
 * Formats statistics string with:
 * - Current state and time in state
 * - Retry count
 * - Sequence number
 * - Session ID
 *
 * @param sm: Client state machine
 * @param buffer: Output buffer for statistics string
 * @param buffer_size: Size of output buffer
 * @return: Number of bytes written, or -1 on error
 */
int client_sm_get_statistics(const client_state_machine_t *sm, char *buffer, size_t buffer_size);

/*
 * server_sm_get_statistics - Get state machine statistics
 * @return: Number of bytes written, or -1 on error
 */
int server_sm_get_statistics(const server_state_machine_t *sm, char *buffer, size_t buffer_size);

#endif /* STATE_MACHINE_H */
