// scene_features_dump — write the C++ scene-boundary feature matrix to HDF5, so
// the XGBoost model is TRAINED on exactly the features the C++ detector produces
// at inference (parity by construction — no numpy re-implementation to keep in
// sync). Reads frames/rgb_hist + frames/timestamp_sec from a dump and, given the
// movie, the per-second audio log-PSD; writes features [T,206] + timestamps.
//
//   scene_features_dump <dump.h5> <movie> <out_features.h5>
//
// The py3.12 venv trainer (train_xgb_cpp.py) reads <out_features.h5>, attaches
// the soft Gaussian boundary target, fits XGBoost, and saves the model that
// XGBSceneBoundary loads. Same C++ features both sides → exact parity.

#include "inference/xgb_scene_boundary.hpp"
#include "inference/audio_logpsd.hpp"
#include <H5Cpp.h>
#include <iostream>
#include <vector>

int main(int argc, char** argv) {
    if (argc < 4) {
        std::cerr << "usage: scene_features_dump <dump.h5> <movie> <out.h5>\n";
        return 1;
    }
    H5::H5File in(argv[1], H5F_ACC_RDONLY);
    H5::DataSet hd = in.openDataSet("frames/rgb_hist");
    hsize_t hdims[2]; hd.getSpace().getSimpleExtentDims(hdims);
    std::vector<float> flat(hdims[0]*hdims[1]);
    hd.read(flat.data(), H5::PredType::NATIVE_FLOAT);
    const int T = hdims[0], C = hdims[1];
    std::vector<std::vector<float>> hist(T, std::vector<float>(C));
    for (int t = 0; t < T; ++t)
        for (int c = 0; c < C; ++c) hist[t][c] = flat[t*C+c];

    H5::DataSet td = in.openDataSet("frames/timestamp_sec");
    hsize_t tdim[1]; td.getSpace().getSimpleExtentDims(tdim);
    std::vector<double> ts(tdim[0]);
    td.read(ts.data(), H5::PredType::NATIVE_DOUBLE);

    auto audio = AudioLogPSD::extract(argv[2]);
    if ((int)audio.size() != T) {
        std::cerr << "[features] audio rows " << audio.size() << " != hist rows "
                  << T << " — aligning (pad/truncate)\n";
        audio.resize(T, std::vector<float>(audio.empty()?57:audio[0].size(), 0.f));
    }

    std::vector<float> X = XGBSceneBoundary::feature_matrix(hist, audio);
    const int F = XGBSceneBoundary::kNFeatures;

    H5::H5File out(argv[3], H5F_ACC_TRUNC);
    hsize_t xd[2] = {(hsize_t)T, (hsize_t)F};
    out.createDataSet("features", H5::PredType::NATIVE_FLOAT, H5::DataSpace(2, xd))
       .write(X.data(), H5::PredType::NATIVE_FLOAT);
    hsize_t td2[1] = {(hsize_t)T};
    out.createDataSet("timestamp_sec", H5::PredType::NATIVE_DOUBLE, H5::DataSpace(1, td2))
       .write(ts.data(), H5::PredType::NATIVE_DOUBLE);
    std::cerr << "[features] wrote [" << T << "," << F << "] → " << argv[3] << "\n";
    return 0;
}
