#pragma once
// batch_capture — the REAPER-free logic behind batch capture (one action fires N
// captures: one bank sample per selected item / per razor area).
//
// PURE MODULE: NO REAPER types, NO SWELL, NO vendor/ includes. Standard library
// only. The batch shell reads the DAW state (selected items -> exact bounds;
// each track's P_RAZOREDITS -> areas) and hands the raw ranges here:
//
//   1. planCaptureUnits: an ordered list of (start,end) ranges -> an ordered
//      list of CaptureUnit, each with a 1-based ordinal and validated bounds.
//      Empty/inverted ranges are dropped (mirrors the offline backend's own
//      end>start guard); ordinals count only the kept units, so three valid
//      items yield 1,2,3 regardless of dropped neighbors.
//   2. BatchOutcome: order-preserving aggregation of per-unit results into a
//      summary (succeeded/failed counts + ordered failures) for one console
//      line with no partial-corruption ambiguity.
//
// Range is the only thing that varies per unit here. FX scope (item vs track) is
// a per-action constant the shell already owns; item-batch uses item scope,
// razor-batch uses track scope, passed through unchanged from the single-capture
// path.

#include <cstddef>
#include <string>
#include <vector>

namespace reasampler::capture {

// One capture in a batch: an exact source range plus its 1-based ordinal within
// the kept set. The ordinal disambiguates per-unit file stems (the offline
// backend's unique tag is 1-second-granular, so a fast batch could otherwise
// collide N files onto one name) and labels a failure in the summary.
struct CaptureUnit {
    int    ordinal      = 0;    // 1-based, counts kept units only
    double startSeconds = 0.0;  // exact — no rounding
    double endSeconds   = 0.0;
};

// A source range handed in by the shell (a selected item's [pos, pos+len] or one
// razor area's [start, end]). Named BatchRange (not SourceRange) to avoid
// collision with bank_model's SourceRange, which carries PPQ fields this planner
// doesn't need.
struct BatchRange {
    double startSeconds = 0.0;
    double endSeconds   = 0.0;
};

// Validates + orders a batch's source ranges into capture units. Preserves input
// order; drops every range with end <= start; assigns 1-based ordinals over the
// kept units. An empty input yields an empty plan — the shell reports "nothing
// to batch" and writes nothing.
std::vector<CaptureUnit> planCaptureUnits(const std::vector<BatchRange>& ranges);

// The per-unit verdict the shell records after each render attempt, in unit order.
struct BatchUnitResult {
    int         ordinal = 0;     // the CaptureUnit's ordinal this result is for
    bool        ok      = false; // true iff the render + bank-add succeeded
    std::string detail;          // failure reason (empty on success) — for the summary
};

// Order-preserving aggregation of a batch's per-unit results. Built incrementally
// by the shell (record() after each unit) so a mid-batch failure doesn't abort
// the remaining units — each unit is independent.
class BatchOutcome {
public:
    // Records one unit's verdict. Order of calls IS the reported order.
    void record(int ordinal, bool ok, std::string detail = {});

    std::size_t total()     const { return results_.size(); }
    std::size_t succeeded() const;
    std::size_t failed()    const;

    const std::vector<BatchUnitResult>& results() const { return results_; }

    // The ordered subset of results that failed (ok == false). For the summary line.
    std::vector<BatchUnitResult> failures() const;

    // A single human summary line for the console (explicit-action response — allowed
    // by the console policy; a batch-completion summary with failure counts qualifies,
    // per-unit success spam does not). `noun` is the unit word ("item" / "razor area").
    // Examples:
    //   all-success, 3 items : "ReaSampler batch capture: 3 items captured."
    //   partial, 3 of 5      : "ReaSampler batch capture: 3 of 5 items captured "
    //                          "(2 failed: #2, #4)."
    //   empty plan           : "ReaSampler batch capture: nothing to capture."
    std::string summaryLine(const std::string& noun) const;

private:
    std::vector<BatchUnitResult> results_;
};

} // namespace reasampler::capture
