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

// Wire validation shared by firmware and host tests. PCM is never dropped silently.
struct SpeechStream {
    std::string id;
    uint32_t sequence = 0;
    bool ended = false;
    bool start(const std::string &next, unsigned rate, unsigned bits, unsigned channels) {
        if (next.empty() || next.size() > 64 || rate != 44100 || bits != 16 || channels != 1) return false;
        id = next; sequence = 0; ended = false; return true;
    }
    bool chunk(const std::string &incoming, double seq, size_t bytes) {
        if (id.empty() || incoming != id) return false; // stale packets cannot cancel new speech
        if (ended || seq != sequence || bytes == 0 || bytes > 7056 || bytes % 2) { stop(); return false; }
        ++sequence; return true;
    }
    bool end(const std::string &incoming, double chunks) {
        if (id.empty() || incoming != id) return false;
        if (ended || chunks != sequence) { stop(); return false; }
        ended = true; return true;
    }
    void stop() { id.clear(); sequence = 0; ended = false; }
};

enum class SpeechMenuAction { NONE, AGENT_SETTINGS, LOAD_SPEECH, SAVE_MODE, READ_SCREEN };
struct SpeechMenu {
    enum class Page { ROOT, SPEECH, MODE };
    Page page = Page::ROOT;
    unsigned index = 0, mode = 0, saved_mode = 0;
    static const char *mode_name(unsigned value) {
        constexpr const char *names[] = {"OFF", "MANUAL", "AUTO_REPLY", "AUTO_SUMMARY"};
        return names[value % 4];
    }
    void open() { page = Page::ROOT; index = 0; }
    void load(const std::string &value) {
        for (unsigned i=0;i<4;++i) if (value == mode_name(i)) mode=saved_mode=i;
    }
    // The wearable shell embeds SPEECH directly under Settings / Agent.
    void open_speech() {page=Page::SPEECH;index=0;mode=saved_mode;}
    // Double A enters the mode selector directly, skipping the Settings chain.
    void open_mode() {page=Page::MODE;index=0;mode=saved_mode;}
    SpeechMenuAction back() {
        if(page==Page::MODE) {mode=saved_mode;page=Page::SPEECH;index=0;return SpeechMenuAction::NONE;}
        open();return SpeechMenuAction::AGENT_SETTINGS;
    }
    SpeechMenuAction click(bool a) {
        if (a) { if (page == Page::MODE) mode=(mode+1)%4; else index=(index+1)%2; return SpeechMenuAction::NONE; }
        if (page == Page::ROOT) {
            if (!index) return SpeechMenuAction::AGENT_SETTINGS;
            page=Page::SPEECH; index=0; return SpeechMenuAction::LOAD_SPEECH;
        }
        if (page == Page::SPEECH) {
            if (index) return SpeechMenuAction::READ_SCREEN;
            page=Page::MODE; return SpeechMenuAction::NONE;
        }
        page=Page::SPEECH; index=0; return SpeechMenuAction::SAVE_MODE;
    }
    std::string label() const {
        if (page==Page::ROOT) return index ? "SPEECH" : "AGENT SETTINGS";
        if (page==Page::MODE) return mode_name(mode);
        return index ? "READ SCREEN NOW" : std::string("SPEECH MODE\n\n")+mode_name(mode);
    }
};
