#pragma once

#include <string>
#include <vector>

namespace fgc {

// Structured decode of the firmware DIAG output stream. The firmware emits
// (interleaved with periodic ST lines), per axis:
//   DG BEGIN <Y|P>
//   DG <Y|P> S<speed> <FWD|REV> ERR_PEAK n ERR_RMS n ERR_STILL n
//            CS_MIN n CS_MAX n SG_MIN n PWM_AVG n FLAGS 0x.. <PASS|FAIL>   (x6)
//   DG <Y|P> RESULT <PASS|FAIL>
//   ... and finally:  DG DONE
// Pure (no I/O); mirrors DumpParser so it can be unit-tested in fgc_core.

struct DiagTest {
    int      speed = 0;          // S<speed>
    bool     fwd = true;         // FWD vs REV
    long     err_peak = 0;       // encoder following error (counts); -1 = no encoder
    long     err_rms = 0;
    long     err_still = 0;
    int      cs_min = 0, cs_max = 0;
    int      sg_min = 0;
    int      pwm_avg = 0;
    unsigned flags = 0;          // fault bitmask
    bool     pass = false;
};

struct DiagAxis {
    char                  axis = '?';     // 'Y' / 'P'
    bool                  has_result = false;
    bool                  pass = false;   // axis RESULT
    std::vector<DiagTest> tests;
};

struct DiagResult {
    bool                  valid = false;  // at least one well-formed DG line
    bool                  done = false;   // saw "DG DONE"
    std::vector<DiagAxis> axes;

    bool allPass() const;                 // every axis with a result passed (and >=1 axis)
};

// Parse a captured DG block (only "DG ..." lines matter; other lines are ignored).
DiagResult parseDiag(const std::string& block);

// Human-readable summary lines for a decoded diag.
std::vector<std::string> formatDiag(const DiagResult& d);

}  // namespace fgc
