// SDK fakes around UNMODIFIED production functions, not a parallel policy model.
#include "wifi_connection_ownership.h"
#include "wifi_selection.h"
#include <atomic>
#include <cassert>
#include <cstdio>
#include <cstring>
#include <functional>
#include <iostream>
#include <mutex>
#include <new>
#include <string>
#include <thread>
#include <vector>
using namespace wearable;
using SemaphoreHandle_t = int;
using esp_err_t = int;
using esp_event_base_t = int;
constexpr int ESP_OK=0, ESP_ERR_INVALID_ARG=-1, ESP_ERR_INVALID_STATE=-2, ESP_ERR_NO_MEM=-3;
constexpr int WIFI_IF_STA=0, WIFI_AUTH_OPEN=0, WIFI_AUTH_WPA2_PSK=1;
constexpr int WIFI_CONNECTED_BIT=1, portMAX_DELAY=100000, pdPASS=1;
constexpr int WIFI_EVENT=1, IP_EVENT=2, WIFI_EVENT_STA_DISCONNECTED=3, IP_EVENT_STA_GOT_IP=4;
constexpr unsigned kConnectTimeoutMs=15000, kDisconnectSettleMs=3000;
#define pdMS_TO_TICKS(x) (x)
#define ESP_LOGI(...) ((void)0)
#define ESP_LOGW(...) ((void)0)
#define IPSTR "%d.%d.%d.%d"
#define IP2STR(x) 0,0,0,0
struct Stop {};
struct wifi_config_t { struct {
    unsigned char ssid[32]{},password[64]{};
    struct {int authmode=0;} threshold;
    struct {bool capable=false,required=false;} pmf_cfg;
} sta; };
struct wifi_ap_record_t {unsigned char ssid[33]{};};
struct wifi_event_sta_disconnected_t {int reason=0;};
struct ip_event_got_ip_t {};
struct Memory:WiFiProfileStorage {
    WiFiStoreImage image{};
    bool present=false, fail_save=false;
    WiFiStoreLoadState load(WiFiStoreImage& out) override {
        out=image;return present?WiFiStoreLoadState::Present:WiFiStoreLoadState::Missing;
    }
    bool save(const WiFiStoreImage& in) override {
        if(fail_save)return false;
        image=in;present=true;return true;
    }
    bool erase() override {present=false;return true;}
} s_storage;
WiFiProfileStore s_store(s_storage);
ConnectionOwnership s_own;
SemaphoreHandle_t s_lock=1,s_own_lock=2,s_transition_lock=3,s_portal_lock=4;
std::recursive_mutex mutexes[5];
int s_events=1;
std::atomic<WifiLinkState> s_state{WifiLinkState::Offline};
std::atomic<ProvisioningMode> s_provisioning{ProvisioningMode::Normal};
std::atomic<CandidateResult> s_last_candidate{CandidateResult::Pending};
std::atomic<bool> s_candidate_pending{false};
std::atomic<unsigned> s_event_generation{0},s_success_sequence{0};
std::atomic<int> s_last_reason{0};
uint32_t s_candidate_generation=0,s_provision_generation=1;
bool s_portal_stopping=false;
char s_current_ssid[33]{},s_candidate_ssid[33]{};
int s_current_profile=-1;
std::string configured,associated;
thread_local std::function<void()> delay_hook,unlock_hook,close_hook;
thread_local unsigned long long now_ms=0;
thread_local int transaction_depth=0;
thread_local bool auto_ip=true;
int set_config_rc=0,connect_rc=0,disconnect_rc=0,connect_calls=0,ap_stops=0;
bool wrong_ap=false,immediate_ip=false;
bool refuse_first_config=false,enforce_disconnected_config=false;
std::atomic<bool> s_approval_pending_hint{false},reporter_waiting{false};
std::mutex display_mutex;
std::atomic<bool> contender_waiting{false},contender_done{false};
const auto main_thread=std::this_thread::get_id();
std::vector<std::pair<void(*)(void*),void*>> queued;
void xSemaphoreTakeRecursive(int id,int) {
    if(id==3 && std::this_thread::get_id()!=main_thread)contender_waiting=true;
    mutexes[id].lock();if(id==3)++transaction_depth;
}
void xSemaphoreGiveRecursive(int id) {
    if(id==3)--transaction_depth;
    mutexes[id].unlock();
    auto hook=unlock_hook;if(id==2 && hook)hook();
}
void xSemaphoreTake(int id,int) {mutexes[id].lock();}
void xSemaphoreGive(int id) {mutexes[id].unlock();}
void xEventGroupClearBits(int,int) {}
void xEventGroupSetBits(int,int) {}
unsigned long long esp_timer_get_time() {return now_ms*1000;}
void vTaskDelay(unsigned ms) {
    now_ms+=ms;
    auto hook=delay_hook;
    if(ms==1500 && close_hook) {auto closing=close_hook;closing();}
    if(ms==50) {
        if(hook)hook();
        else if(auto_ip)++s_event_generation;
    }
    if(ms==5000 || ms==1000 || ms==200)throw Stop{};
}
void vTaskDelete(void*) {throw Stop{};}
int xTaskCreate(void(*fn)(void*),const char*,int,void* context,int,void*) {
    queued.emplace_back(fn,context);return pdPASS;
}
void lock_display() {display_mutex.lock();}
void unlock_display() {display_mutex.unlock();}
void board_set_wifi_status(bool,const char*) {
    assert(transaction_depth==0);
    reporter_waiting=true;
    std::lock_guard<std::mutex> display(display_mutex);
}
bool wifi_manager_setup_blocked();
int esp_wifi_sta_get_ap_info(wifi_ap_record_t* ap) {
    if(associated.empty())return -1;
    std::memcpy(ap->ssid,associated.c_str(),associated.size()+1);return 0;
}
int esp_wifi_disconnect() {if(disconnect_rc)return disconnect_rc;associated.clear();return 0;}
int esp_wifi_set_config(int,const wifi_config_t* cfg) {
    if(refuse_first_config) {refuse_first_config=false;return -1;}
    if(enforce_disconnected_config && !associated.empty())return -1;
    if(set_config_rc)return set_config_rc;
    configured=std::string((const char*)cfg->sta.ssid,strnlen((const char*)cfg->sta.ssid,32));return 0;
}
int esp_wifi_connect() {
    ++connect_calls;if(connect_rc)return connect_rc;
    associated=wrong_ap?"A":configured;
    if(immediate_ip)++s_event_generation;
    return 0;
}
void stop_access_point() {++ap_stops;}
void wifi_manager_stop_provisioning();
#include "wifi_manager.inc"

void reset() {
    s_own=ConnectionOwnership{};s_storage.fail_save=false;
    s_store.clear();s_store.add_or_replace("A","synthetic-only");
    s_state=WifiLinkState::Offline;s_provisioning=ProvisioningMode::Normal;
    s_candidate_pending=false;s_candidate_generation=0;s_provision_generation=1;s_portal_stopping=false;
    s_event_generation=0;s_success_sequence=0;s_last_reason=0;s_last_candidate=CandidateResult::Pending;
    s_current_ssid[0]=0;s_current_profile=-1;configured.clear();associated.clear();
    delay_hook={};unlock_hook={};close_hook={};now_ms=0;auto_ip=true;
    set_config_rc=0;connect_rc=0;disconnect_rc=0;connect_calls=0;ap_stops=0;
    wrong_ap=false;immediate_ip=false;s_approval_pending_hint=false;reporter_waiting=false;
    refuse_first_config=false;enforce_disconnected_config=false;
    contender_waiting=false;contender_done=false;
    assert(queued.empty());assert(transaction_depth==0);
}
CandidateResult validate(const char* ssid) {
    ConnectionAttempt attempt;
    {TransitionGuard transaction;attempt=own_take_candidate(ssid);}
    return validate_candidate(ssid,"synthetic-only",attempt);
}
void run_station() {try {station_task(nullptr);}catch(const Stop&) {}}
void run_queued(size_t index=0) {
    const auto job=queued.at(index);queued.erase(queued.begin()+index);
    try {job.first(job.second);}catch(const Stop&) {}
}
void assert_b() {
    assert(associated=="B");assert(std::string(s_current_ssid)=="B");
    assert(s_own.station_steady());assert(s_state==WifiLinkState::Connected);
}
int main() {
    reset();
    delay_hook=[] {
        delay_hook={};assert(validate("B")==CandidateResult::Success);
    };
    run_station();assert_b();assert(s_success_sequence==1);
    std::cout<<"Old station waiter cannot clear a successful B connection PASS\n";

    reset();std::thread candidate;
    unlock_hook=[&] {
        if(s_own.station_steady() && std::string(s_own.connected_ssid())=="A") {
            unlock_hook={};
            candidate=std::thread([] {assert(validate("B")==CandidateResult::Success);contender_done=true;});
            while(!contender_waiting)std::this_thread::yield();
            // The real candidate task has attempted the mutex; it cannot take
            // over between this production resolve and the following commit.
            assert(transaction_depth>0);assert(!contender_done);
        }
    };
    run_station();candidate.join();assert_b();assert(s_success_sequence==2);
    std::cout<<"Concurrent takeover cannot interleave resolve and durable commit PASS\n";

    reset();s_provisioning=ProvisioningMode::Provisioning;
    assert(wifi_manager_test_candidate("B","synthetic-only")==ESP_OK);
    assert(s_candidate_pending);assert(wifi_manager_preempt_for_approval());
    run_queued();assert(connect_calls==0);assert(s_store.count()==1);
    assert(!s_candidate_pending);assert(s_last_candidate!=CandidateResult::Success);
    std::cout<<"Approval invalidates queued Portal worker before any driver call PASS\n";

    reset();s_provisioning=ProvisioningMode::Provisioning;
    assert(wifi_manager_test_candidate("B","synthetic-only")==ESP_OK);
    assert(wifi_manager_preempt_for_approval());s_provisioning=ProvisioningMode::Provisioning;
    assert(wifi_manager_test_candidate("C","synthetic-only")==ESP_OK);
    run_queued();assert(s_candidate_pending);assert(s_last_candidate==CandidateResult::Pending);
    run_queued();assert(std::string(s_current_ssid)=="C");assert(!s_candidate_pending);
    std::cout<<"Old worker cannot clear or overwrite a newer request PASS\n";

    reset();s_provisioning=ProvisioningMode::Provisioning;
    assert(wifi_manager_test_candidate("B","synthetic-only")==ESP_OK);
    close_hook=[] {
        close_hook={};assert(wifi_manager_test_candidate("C","synthetic-only")==ESP_OK);
    };
    run_queued();assert(s_candidate_pending);assert(ap_stops==0);
    assert(s_provisioning==ProvisioningMode::Provisioning);
    run_queued();assert(std::string(s_current_ssid)=="C");assert(ap_stops==1);
    std::cout<<"Delayed Portal cleanup cannot cancel a newer candidate PASS\n";

    reset();s_provisioning=ProvisioningMode::Provisioning;
    delay_hook=[] {
        delay_hook={};assert(wifi_manager_preempt_for_approval());
        TransitionGuard transaction;
        const auto a=own_station_begin("A");associated="A";
        assert(own_station_resolve(a,true,"A")==AttemptOutcome::Accepted);
        apply_success("A");set_state(WifiLinkState::Connected);
    };
    assert(validate("B")==CandidateResult::Failed);
    assert(associated=="A");assert(std::string(s_current_ssid)=="A");assert(s_own.station_steady());
    assert(s_store.count()==1);
    std::cout<<"Preempted active candidate's late result leaves new A untouched PASS\n";

    reset();set_config_rc=-1;
    assert(validate("B")!=CandidateResult::Success);assert(s_store.count()==1);assert(connect_calls==0);
    reset();connect_rc=-1;
    assert(validate("B")!=CandidateResult::Success);assert(s_store.count()==1);
    reset();wrong_ap=true;
    assert(validate("B")!=CandidateResult::Success);assert(s_store.count()==1);
    reset();disconnect_rc=-1;
    assert(validate("B")!=CandidateResult::Success);assert(connect_calls==0);
    std::cout<<"Driver failures and associated-SSID mismatch never persist B PASS\n";

    reset();s_storage.fail_save=true;
    assert(validate("B")==CandidateResult::StorageError);
    assert(!s_own.station_steady());assert(s_state==WifiLinkState::Offline);
    WiFiProfileStore durable(s_storage);durable.load();
    assert(durable.count()==1 && durable.at(0).same_ssid("A"));
    std::cout<<"Storage failure releases the unpersisted link for recovery PASS\n";

    reset();s_provisioning=ProvisioningMode::Provisioning;connect_rc=-1;
    assert(validate("C")!=CandidateResult::Success);assert(s_own.owner()==ConnectionOwner::None);
    connect_rc=0;run_station();assert(associated=="A");assert(s_own.station_steady());assert(ap_stops==0);
    assert(s_provisioning==ProvisioningMode::Provisioning);
    std::cout<<"Failed candidate releases ownership and restores A with Portal still active PASS\n";

    reset();s_store.add_or_replace("B","synthetic-only");
    s_store.mark_success("A",10);s_success_sequence=10;
    delay_hook=[] {
        delay_hook={};associated.clear();now_ms+=kConnectTimeoutMs;
        wifi_event_sta_disconnected_t event{201};
        handle_wifi_event(nullptr,WIFI_EVENT,WIFI_EVENT_STA_DISCONNECTED,&event);
    };
    run_station();assert_b();assert(connect_calls==2);
    std::cout<<"Pending station A disconnect still falls back to known B PASS\n";

    reset();s_store.add_or_replace("B","synthetic-only");
    s_store.mark_success("A",10);s_success_sequence=10;
    associated="old-link";refuse_first_config=true;enforce_disconnected_config=true;
    run_station();assert_b();assert(connect_calls==1);
    std::cout<<"Station driver failure cleans the old link before trying B PASS\n";

    reset();immediate_ip=true;auto_ip=false;
    assert(validate("B")==CandidateResult::Success);assert_b();assert(now_ms==0);
    std::cout<<"GOT_IP during connect is observed (snapshot before connect) PASS\n";

    reset();assert(validate("B")==CandidateResult::Success);
    const wifi_event_sta_disconnected_t event{201};
    handle_wifi_event(nullptr,WIFI_EVENT,WIFI_EVENT_STA_DISCONNECTED,const_cast<wifi_event_sta_disconnected_t*>(&event));
    assert_b();
    associated.clear();handle_wifi_event(nullptr,WIFI_EVENT,WIFI_EVENT_STA_DISCONNECTED,const_cast<wifi_event_sta_disconnected_t*>(&event));
    assert(!s_own.station_steady());assert(s_current_ssid[0]==0);
    std::cout<<"Late disconnect cannot clear new association; genuine disconnect releases steady state PASS\n";

    reset();display_mutex.lock();s_approval_pending_hint=true;
    {
        TransitionGuard transaction;
        assert(wifi_manager_setup_blocked()); // must not acquire the display lock
    }
    std::thread reporter([] {try {wifi_status_task(nullptr);}catch(const Stop&) {}});
    while(!reporter_waiting)std::this_thread::yield();
    {TransitionGuard transaction;} // UI -> Wi-Fi remains possible while reporting waits for UI
    display_mutex.unlock();reporter.join();
    std::cout<<"Approval snapshot is lock-free; UI reporting never holds Wi-Fi locks PASS\n";
}
