#pragma once
#include "ui_state.h"
#include "typography.h"
#include "agent_display.h"
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <string>
#include <vector>

namespace wearable {
struct ShellView {
    bool selected=false,wifi=false,gateway=false;
    const char *agent="",*project="",*session="",*model="",*effort="",*state="IDLE";
    const char *activity_type="",*activity="",*recent="",*final_text=nullptr;
    const char *time="--:--",*date="Time unavailable",*battery="BAT --",*firmware="",*wifi_detail="";
    const char *save_feedback="";
    uint64_t elapsed=0,now_ms=0,last_update_ms=0;
    int rssi=-127;
};

template<class Gfx,class Fonts> class ShellRenderer {
    Gfx& g;const Fonts& fonts;const UiState& ui;const ShellView& v;Palette p;
    void setup(TypeRole role,uint16_t color,uint16_t background=0) {
        fonts.apply(g,role,ui.preferences.text_size,color,background);
    }
    size_t character_size(const char* value,size_t remain) const {
        const auto first=uint8_t(value[0]);
        const size_t wanted=(first&0xf8)==0xf0?4:(first&0xf0)==0xe0?3:(first&0xe0)==0xc0?2:1;
        return std::min(remain,wanted);
    }
    std::string fit(const char* value,int width) {
        std::string text=value?value:"";
        if(g.textWidth(text.c_str())<=width) return text;
        std::string out;
        for(size_t i=0;i<text.size();) {
            const size_t n=character_size(text.data()+i,text.size()-i);
            auto next=out+text.substr(i,n);
            if(g.textWidth((next+"...").c_str())>width) break;
            out=next;i+=n;
        }
        return out+"...";
    }
    void center(const char* text,int y,int width=304) {
        auto clipped=fit(text,width);g.drawString(clipped.c_str(),234-g.textWidth(clipped.c_str())/2,y);
    }
    std::vector<std::string> wrap(const char* value,int width) {
        std::vector<std::string> lines;std::string current;
        if(!value) return lines;
        const size_t length=std::strlen(value);
        for(size_t i=0;i<length;) {
            if(value[i]=='\n') {lines.push_back(current);current.clear();++i;continue;}
            const size_t n=character_size(value+i,length-i);
            auto next=current+std::string(value+i,n);
            if(!current.empty() && g.textWidth(next.c_str())>width) {lines.push_back(current);current.assign(value+i,n);}
            else current=next;
            i+=n;
        }
        if(!current.empty()) lines.push_back(current);
        return lines;
    }
    uint16_t state_color(const char* state=nullptr) const {
        state=state?state:v.state;
        return !std::strcmp(state,"RUNNING")?p.accent:!std::strcmp(state,"DONE")?p.done:
            !std::strcmp(state,"FAILED")?p.failed:!std::strcmp(state,"WAITING_APPROVAL")?p.approval:p.secondary;
    }
    std::string duration(bool with_state=false) const {
        char text[48];
        if(with_state) std::snprintf(text,sizeof(text),"%s  %02llu:%02llu",v.state,
            (unsigned long long)(v.elapsed/60),(unsigned long long)(v.elapsed%60));
        else std::snprintf(text,sizeof(text),"%02llu:%02llu",
            (unsigned long long)(v.elapsed/60),(unsigned long long)(v.elapsed%60));
        return text;
    }
    void rule(int y) {g.fillRoundRect(96,y,276,2,1,p.selected);}
    void body(const char* text,int top,int bottom,bool tail=false) {
        setup(TypeRole::AgentBody,p.primary);
        auto lines=wrap(text,288);
        const int line_height=g.fontHeight()+2;
        const size_t count=std::max(1,(bottom-top)/line_height);
        const size_t pages=std::max<size_t>(1,(lines.size()+count-1)/count);
        const size_t start=tail&&lines.size()>count?lines.size()-count:
            pages>1?((v.now_ms/6000)%pages)*count:0;
        for(size_t i=start;i<std::min(start+count,lines.size());++i)
            g.drawString(lines[i].c_str(),90,top+int(i-start)*line_height);
        if(pages>1&&!tail) {
            char page[28];std::snprintf(page,sizeof(page),"Result %u/%u",unsigned(start/count+1),unsigned(pages));
            setup(TypeRole::Footer,p.secondary);center(page,bottom+2,304);
        }
    }
    void settings_hint(const char* first) {
        setup(TypeRole::Footer,p.accent);center(first,381,300);
        setup(TypeRole::Footer,p.secondary);center(*v.save_feedback?v.save_feedback:"Hold B to close",407,270);
    }
public:
    ShellRenderer(Gfx& gfx,const Fonts& f,const UiState& state,const ShellView& view)
        :g(gfx),fonts(f),ui(state),v(view),p(palette(state.preferences.theme)) {}
    void watch() {
        setup(TypeRole::Meta,p.secondary);
        std::string status=std::string(v.battery)+(v.wifi?"   Wi-Fi":"   Wi-Fi --");
        center(status.c_str(),38,190);
        center(v.gateway?"Agent online":"Agent offline",64,180);
        setup(TypeRole::WatchTime,p.primary);center(v.time,126,360);
        setup(TypeRole::WatchDate,p.secondary);center(v.date,244,330);
        const char* shown_state=!v.gateway?"OFFLINE":v.selected?v.state:"IDLE";
        setup(TypeRole::StatusPrimary,state_color(shown_state));
        center(v.gateway&&v.selected&&!std::strcmp(v.state,"RUNNING")?duration(true).c_str():
            v.selected?shown_state:"AGENT IDLE",304,330);
    }
    void agent() {
        const char* shown_state=!v.gateway?"OFFLINE":v.state;
        setup(TypeRole::PageTitle,state_color(shown_state));
        std::string heading=std::string(v.selected?v.agent:"AGENT")+"    "+
            (v.selected?(!std::strcmp(shown_state,"RUNNING")?duration(true):shown_state):"IDLE");
        center(heading.c_str(),52,240);
        setup(TypeRole::Meta,p.secondary);center(v.selected?v.session:"No session selected",80,300);
        std::string meta;
        if(v.selected) {
            meta=v.project;
            if(*v.model) meta+="  /  "+std::string(v.model);
            if(*v.effort) meta+="  /  "+std::string(v.effort);
        } else meta="Select an Agent from Admin";
        setup(TypeRole::Footer,p.secondary);center(meta.c_str(),103,310);
        rule(125);
        const auto shown=agent_display_text(v.state,v.final_text,v.activity_type,v.activity,v.recent);
        setup(TypeRole::Meta,shown.tool?p.accent:p.secondary);
        center(shown.terminal?"FINAL RESPONSE":shown.tool?"TOOL ACTIVITY":"LIVE ACTIVITY",133,270);
        const char* text=shown.text;
        if(!text||!*text) text="Waiting for agent activity...";
        body(text,154,404,!shown.terminal);
    }
    void help() {
        setup(TypeRole::PageTitle,p.primary);center("HELP",48,260);
        setup(TypeRole::StatusPrimary,p.accent);center("Wearable Agent Console",86,330);
        setup(TypeRole::Meta,p.secondary);center("View, control and talk to",126,310);center("your cloud AI agents.",151,310);
        rule(186);
        setup(TypeRole::AgentBody,p.primary);
        const int line=g.fontHeight()+5;int y=205;
        for(const char* value:{"A  Next page","B  Previous page","Hold A  Voice","Hold B  Settings"}) {
            center(value,y,310);y+=line;
        }
        setup(TypeRole::Footer,p.secondary);
        center("Approval: A Approve / B Reject",371,310);
        center("Voice: A Send / B Cancel",397,280);
    }
    void settings() {
        setup(TypeRole::PageTitle,p.primary);center("SETTINGS",48,280);
        if(ui.menu==Menu::Edit) {
            const char* title="";std::string value;
            switch(ui.field) {
            case Field::Brightness:title="Brightness";value=std::to_string(ui.draft.brightness)+"%";break;
            case Field::Vibration:title="Vibration";value=ui.draft.vibration_enabled?"On":"Off";break;
            case Field::HomeScreen:title="Home Screen";value=home_name(ui.draft.home_screen);break;
            case Field::Text:title="Text Size";value=text_name(ui.draft.text_size);break;
            case Field::Theme:title="Theme";value=theme_name(ui.draft.theme);break;
            }
            setup(TypeRole::StatusSecondary,p.secondary);center(title,138);
            setup(TypeRole::AgentBodyLarge,p.accent);center(value.c_str(),205);
            setup(TypeRole::Meta,p.secondary);center(ui.field==Field::Brightness?"Live preview - B to save":"Draft - B to apply",276);
            settings_hint("A NEXT   B APPLY");return;
        }
        std::vector<std::string> rows;
        switch(ui.menu) {
        case Menu::Root:rows={"Agent","Device","Display","System","Back"};break;
        case Menu::Agent:rows={v.gateway&&v.selected?"Model / Effort":"Model / Effort unavailable","Speech Mode","Back"};break;
        case Menu::Device:rows={"Brightness  "+std::to_string(ui.preferences.brightness)+"%",std::string("Vibration  ")+(ui.preferences.vibration_enabled?"On":"Off"),"Back"};break;
        case Menu::Display:rows={std::string("Home  ")+home_name(ui.preferences.home_screen),std::string("Text  ")+text_name(ui.preferences.text_size),std::string("Theme  ")+theme_name(ui.preferences.theme),"WatchFace Agent Clock","Back"};break;
        case Menu::System:{
            char wifi[64];std::snprintf(wifi,sizeof(wifi),"Wi-Fi %s  %d dBm",v.wifi?"CONNECTED":"--",v.rssi);
            rows={v.battery,wifi,v.gateway?"Gateway ONLINE":"Gateway RECONNECTING",std::string("Firmware ")+v.firmware,"Back"};break;
        }
        default:break;
        }
        size_t first=ui.index>1?ui.index-1:0;
        if(first+3>rows.size()) first=rows.size()>3?rows.size()-3:0;
        for(size_t i=first;i<std::min(first+3,rows.size());++i) {
            const int y=129+int(i-first)*72;
            if(i==ui.index) g.fillRoundRect(82,y-7,304,62,10,p.selected);
            setup(TypeRole::AgentBody,i==ui.index?p.accent:p.secondary,i==ui.index?p.selected:0);
            center(rows[i].c_str(),y,286);
        }
        settings_hint("A NEXT   B SELECT");
    }
};
} // namespace wearable
