#ifndef NAIL_LED_MAPPER_H
#define NAIL_LED_MAPPER_H

#include <stdbool.h>
#include <stdint.h>

#define NLM_MAX_CHANNELS 122u
#define NLM_GRID_WIDTH 16u
#define NLM_GRID_HEIGHT 12u
#define NLM_GRID_CELLS (NLM_GRID_WIDTH * NLM_GRID_HEIGHT)

typedef struct {
    uint32_t optical_calibration_id;
    uint16_t channels;
    bool calibrated;
    const uint8_t (*irradiance_weights)[NLM_GRID_CELLS];
    const uint8_t *max_pwm;
} nlm_profile;

typedef struct {
    uint32_t optical_calibration_id;
    uint64_t frame_seq;
    uint64_t capture_baseline_seq;
    uint64_t min_source_frame_seq;
    uint64_t last_accepted_frame_seq;
    bool exposure_started_after_request;
    bool model_valid;
    bool hand_present;
    uint8_t model_confidence;
    const uint8_t *nail_probability;
} nlm_frame;

typedef struct {
    uint32_t optical_calibration_id;
    uint16_t minimum_nail_energy_permille;
    uint8_t minimum_model_confidence;
    uint8_t requested_pwm;
} nlm_policy;

typedef struct {
    uint16_t channels;
    uint8_t channel_mask[NLM_MAX_CHANNELS];
    uint8_t pwm[NLM_MAX_CHANNELS];
    uint16_t nail_energy_permille[NLM_MAX_CHANNELS];
} nlm_result;

typedef enum {
    NLM_OK = 0,
    NLM_INVALID_ARGUMENT,
    NLM_UNCALIBRATED,
    NLM_INVALID_POLICY,
    NLM_STALE_FRAME,
    NLM_INVALID_MODEL,
    NLM_NO_HAND
} nlm_status;

/*
 * Builds a fail-dark per-channel mask from a fresh nail-probability grid and
 * a factory-measured, wavelength-specific irradiance map. The caller owns the
 * profile storage; it must remain immutable while this function runs.
 */
nlm_status nlm_map_frame(const nlm_profile *profile,
                         const nlm_policy *policy,
                         const nlm_frame *frame,
                         nlm_result *result);

#endif
