#pragma once
// CROWD-CONTRACT-01: SDK-free seam. NOT a registered DeepStream processor.
// Values must come from a reviewed weight/export manifest; an empty contract
// rejects. Checks below validate declarations, not the truth of their provenance.
#include <algorithm>
#include <cstdint>
#include <string>
#include <vector>

namespace contextra {
struct CrowdRawContract {
    uint32_t queries = 0;
    uint32_t logits = 0;
    int personSlot = -1;
    int headSlot = -1;
    std::vector<int> ignoredSlots;
    std::string checkpointSha256, onnxSha256, reviewId;
    std::string boxFormat, scoreFormat, selectionPolicy;
};
inline bool crowdHash(const std::string& value) {
    return value.size() == 64 && std::all_of(value.begin(), value.end(), [](char c) {
        return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f');
    });
}
inline bool validateCrowdDeclaration(const CrowdRawContract& c) {
    if (c.queries < 1 || c.queries > 4096 || c.logits < 2 || c.logits > 256
        || !crowdHash(c.checkpointSha256) || !crowdHash(c.onnxSha256)
        || c.reviewId.empty() || c.reviewId.size() > 128
        || c.boxFormat != "CXCYWH_NORMALIZED" || c.scoreFormat != "RAW_SIGMOID_LOGITS"
        || c.selectionPolicy != "GLOBAL_TOP300_THEN_MAP") return false;
    auto slots = c.ignoredSlots;
    slots.push_back(c.personSlot); slots.push_back(c.headSlot);
    std::sort(slots.begin(), slots.end());
    if (slots.size() != c.logits) return false;
    for (uint32_t i=0; i<c.logits; ++i) if (slots[i] != static_cast<int>(i)) return false;
    return true;
}
inline bool validateCrowdTensorContract(const CrowdRawContract& c,
        const std::vector<uint32_t>& dets, const std::vector<uint32_t>& labels,
        uint32_t batch, bool detsFp32, bool labelsFp32) {
    return validateCrowdDeclaration(c) && batch >= 1 && batch <= 8 && detsFp32 && labelsFp32
        && dets == std::vector<uint32_t>{batch,c.queries,4}
        && labels == std::vector<uint32_t>{batch,c.queries,c.logits};
}
inline int crowdCanonicalClass(const CrowdRawContract& c, uint32_t slot) {
    return static_cast<int>(slot) == c.personSlot ? 0 :
           static_cast<int>(slot) == c.headSlot ? 1 : -1;
}
}  // namespace contextra
