#pragma once
#include <array>
#include <cstdint>
#include <string>

// Hardware-independent modal controller, exercised by host C++ tests.
// Gateway owns the FIFO; at most four in-flight presentations fit locally.
struct ApprovalView {
    std::string id, agent, title, detail;
    uint64_t expires_ms = 0;
    std::array<std::string,4> choices{};
    uint8_t choice_count=0;
};
struct ApprovalAction { std::string id; bool approve = false; std::string decision; };
class ApprovalControl {
public:
    uint64_t generation = 1;
    std::string result;
    uint64_t result_until = 0;
    bool submitted = false;
    uint8_t choice_index=0;
    bool modal() const { return count_ || result_until; }
    const ApprovalView *current() const { return count_ && !result_until ? &queue_[0] : nullptr; }
    bool receive(const ApprovalView &view, uint64_t /*now*/) {
        if (view.id.empty() || view.id.size() > 64) return false;
        for (size_t i = 0; i < count_; ++i) if (queue_[i].id == view.id) return false;
        if (count_ == queue_.size()) return false;
        queue_[count_++] = view;
        if (count_ == 1) { ++generation; submitted = false; choice_index=0; }
        return true;
    }
    bool finish(const std::string &id, const std::string &state, uint64_t now) {
        for (size_t i = 0; i < count_; ++i) {
            if (queue_[i].id != id) continue;
            const bool front = i == 0;
            for (size_t j = i+1; j < count_; ++j) queue_[j-1] = queue_[j];
            queue_[--count_] = {};
            if (front) {
                ++generation; submitted = false;choice_index=0;
                if (state == "APPROVED" || state == "REJECTED") {
                    result = state; result_until = now + 1000;
                } else { result.clear(); result_until = 0; }
            }
            return true;
        }
        return false;
    }
    bool tick(uint64_t now) {
        bool changed = false;
        if (result_until && now >= result_until) {
            result_until = 0; result.clear(); ++generation; changed = true;
        }
        return changed;
    }
    ApprovalAction release(bool button_a, uint64_t pressed_generation, uint64_t now) {
        tick(now);
        if (!current() || submitted || pressed_generation != generation) return {};
        if(queue_[0].choice_count>2 && button_a) {choice_index=(choice_index+1)%queue_[0].choice_count;return {};}
        const auto decision=queue_[0].choice_count?queue_[0].choices[queue_[0].choice_count==2?(button_a?0:1):choice_index]:"";
        submitted = true;
        ++generation; // A simultaneous second button cannot resolve the next item.
        return {queue_[0].id, button_a,decision};
    }
    void disconnect() {
        count_ = 0; queue_ = {}; result.clear(); result_until = 0;
        submitted = false; ++generation;
    }
private:
    std::array<ApprovalView, 4> queue_{};
    size_t count_ = 0;
};
