// local_puzzles.h — wiring layer: QR and sound puzzles → puzzle_state.
#pragma once
#include <stddef.h>
#include <stdint.h>
#include "esp_err.h"
#include "puzzle_state.h"

// Store the aggregation target. Must be called before arm_*.
void      local_puzzles_init(puzzle_state_t *state);

// Arm the QR sequence puzzle. expected[0..count-1] are the QR strings to
// match in order. On solve, reports fragment[0..frag_len) for puzzle_id into
// puzzle_state. Caller buffers may be transient — contents are copied.
// Returns ESP_ERR_INVALID_STATE if init not called OR if the QR puzzle is
//   still running (including the async teardown window after disarm) — retry
//   after ~100 ms.
// Returns ESP_ERR_INVALID_ARG if puzzle_id out of range [1,PUZZLE_MAX_ID],
//   frag_len > PUZZLE_MAX_FRAG, or fragment is NULL when frag_len > 0.
// CALLBACK SAFETY: do not call arm_qr or disarm from the solved callback;
//   defer to another task (e.g. via task notification or event group).
esp_err_t local_puzzles_arm_qr(uint8_t puzzle_id,
                               const char *const *expected, size_t count,
                               const uint8_t *fragment, uint8_t frag_len);

// Arm the sound/melody puzzle. expected[0..count-1] are MIDI note numbers;
// tol is the accepted semitone deviation. On solve, reports fragment[0..frag_len)
// for puzzle_id into puzzle_state. Caller buffers may be transient — copied.
// mic_broker_init() must have been called first.
// Returns ESP_ERR_INVALID_STATE if init not called OR if the sound puzzle is
//   still running (broker is in MIC_P1_SOUND mode).
// Returns ESP_ERR_INVALID_ARG if puzzle_id out of range [1,PUZZLE_MAX_ID],
//   frag_len > PUZZLE_MAX_FRAG, or fragment is NULL when frag_len > 0.
// CALLBACK SAFETY: do not call arm_sound or disarm from the solved callback;
//   defer to another task.
esp_err_t local_puzzles_arm_sound(uint8_t puzzle_id,
                                  const int *expected, size_t count, int tol,
                                  const uint8_t *fragment, uint8_t frag_len);

// Stop both puzzles. QR teardown is asynchronous (see qr_puzzle.h).
void      local_puzzles_disarm(void);
