// See resample_name.h.

#include "core/model/resample_name.h"

#include <cctype>

namespace reasampler::model {

namespace {

constexpr const char* kFallbackStem = "resample";
constexpr int kFirstIteration = 2;  // the source itself is iteration 1

// The " r<digits>" tail, if the name ends in one and the digits are a whole number > 0.
// Returns 0 (no tail) otherwise; `stemLength` is then left untouched.
int trailingIteration(const std::string& name, std::size_t& stemLength) {
    std::size_t digitsBegin = name.size();
    while (digitsBegin > 0 && std::isdigit(static_cast<unsigned char>(name[digitsBegin - 1])))
        --digitsBegin;
    if (digitsBegin == name.size()) return 0;             // no digits at the end
    if (digitsBegin < 2) return 0;                        // no room for " r"
    if (name[digitsBegin - 1] != 'r' || name[digitsBegin - 2] != ' ') return 0;

    // Overflow-safe accumulate: a pathological digit run stops counting rather than
    // wrapping into a small number and silently reusing an existing name.
    int value = 0;
    for (std::size_t i = digitsBegin; i < name.size(); ++i) {
        if (value > 1000000) return 0;
        value = value * 10 + (name[i] - '0');
    }
    if (value <= 0) return 0;
    stemLength = digitsBegin - 2;
    return value;
}

}  // namespace

std::string nextIterationName(const std::string& sourceName) {
    if (sourceName.empty())
        return std::string(kFallbackStem) + " r" + std::to_string(kFirstIteration);

    std::size_t stemLength = sourceName.size();
    const int current = trailingIteration(sourceName, stemLength);
    if (current > 0)
        return sourceName.substr(0, stemLength) + " r" + std::to_string(current + 1);
    return sourceName + " r" + std::to_string(kFirstIteration);
}

}  // namespace reasampler::model
