// bank_sync.cpp — see bank_sync.h. Pure; standard library only.

#include "core/instrument/map/bank_sync.h"

#include <cstdint>
#include <string>

#include "core/wire/wire.h"

namespace reasampler::instrument::map {

std::int64_t parseBankGeneration(const std::string& raw) {
    // Whole-string, non-negative decimal parse, no exceptions/locale surprises (core/wire's
    // guarded accumulate). Leading sign, non-digit, empty, or int64 overflow -> absent (0).
    std::int64_t value = 0;
    if (!wire::parseUnsignedDecimal(raw, value)) return kBankGenerationAbsent;
    return value;
}

std::string formatBankGeneration(std::int64_t generation) {
    return std::to_string(generation);
}

bool bankGenerationChanged(std::int64_t seen, std::int64_t current) {
    return current != seen;
}

AssignConsumeDecision consumeDecision(const std::optional<AssignmentRequest>& request,
                                      std::int64_t lastConsumed, bool resolves,
                                      bool isFocusedTarget) {
    AssignConsumeDecision d;
    d.consumedGeneration = lastConsumed;  // default: nothing changes

    // Rule 1: no request, or not newer than what we already consumed.
    if (!request) return d;
    if (request->generation <= lastConsumed) return d;

    // Rule 2: new but not our target -> don't advance the marker, stay eligible.
    if (!isFocusedTarget) return d;

    // New and our target: consumed-as-seen either way.
    d.consumedGeneration = request->generation;

    // Rule 3: unresolvable -> drop silently, marker already advanced above.
    if (!resolves) return d;

    // Rule 4: new, target, resolvable -> apply.
    d.apply = true;
    d.bankId = request->bankId;
    d.sampleId = request->sampleId;
    return d;
}

}  // namespace reasampler::instrument::map
