#include "With_Loop_Coro.h"
#include "io_coro.h"
#include <string_view>
With_Loop_Coro::~With_Loop_Coro() = default;
void With_Loop_Coro::async_stop() {
    std::string name = type + ":" + key;
    set_state(State::Force_Quit, std::format("任务正常收到请求,等待退出 {}!\n", name).c_str());
    loop_running = false;
}
void With_Loop_Coro::sync_wait() {
    std::string name = type + ":" + key;
    if (!loop_task) {
        std::cout << std::format("{}退出成功！ loop_task 未启动 \n", name);
        return;
    }
    while (loop_task->wait_for(std::chrono::milliseconds(0)) != std::future_status::ready) {
        std::cout << std::format("{}等待退出  当前状态为{} \n", name, Psc::to_string(this->state.load()));
        std::this_thread::sleep_for(std::chrono::milliseconds(1000));
    }
    std::cout << std::format("{}退出成功！ \n", name);
}
bool With_Loop_Coro::running() const {
    return loop_running.load();
}
std::uint64_t With_Loop_Coro::unix_ms() {
    return static_cast<std::uint64_t>(std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count());
}
void With_Loop_Coro::set_state(State next_state, std::string_view action) {
    const auto old_state = state.exchange(next_state);
    if (old_state != next_state) {
        const auto now = unix_ms();
        state_changed_unix_ms_ = now;
        if (next_state == State::Loop_Running) {
            ++start_total_;
            last_started_unix_ms_ = now;
            active_since_unix_ms_ = now;
        }
        if (next_state == State::Start && old_state == State::Waiting_Stop_Loop) {
            ++stop_total_;
            last_stopped_unix_ms_ = now;
            active_since_unix_ms_ = 0;
        }
    }
    if (!action.empty()) {
        std::string name = type + "_" + key;
        std::cout << std::format("协程状态机 {} {}  {} ==> {} \n", name, action, Psc::to_string(old_state),
                                 Psc::to_string(next_state));
    }
}
Psc::JSON With_Loop_Coro::lifecycle_state_json() const {
    const auto active_since = active_since_unix_ms_.load();
    Psc::JSON ret = Psc::JSON::object();
    ret.append({"task_state", Psc::to_string(state.load())});
    ret.append({"enabled", enabled()});
    ret.append({"running", running()});
    ret.append({"state_changed_unix_ms", state_changed_unix_ms_.load()});
    ret.append({"start_total", start_total_.load()});
    ret.append({"stop_total", stop_total_.load()});
    ret.append({"exception_total", exception_total_.load()});
    ret.append({"last_started_unix_ms", last_started_unix_ms_.load()});
    ret.append({"last_stopped_unix_ms", last_stopped_unix_ms_.load()});
    ret.append({"active_duration_ms", active_since == 0 ? 0 : unix_ms() - active_since});
    {
        std::lock_guard lock(exception_mtx_);
        ret.append({"last_exception", last_exception_});
    }
    return ret;
}
void With_Loop_Coro::record_exception(std::string error) {
    ++exception_total_;
    std::lock_guard lock(exception_mtx_);
    last_exception_ = std::move(error);
}
With_Loop_Coro::With_Loop_Coro() : stop(0.1) {
    state_changed_unix_ms_ = unix_ms();
}
asio::awaitable<void> With_Loop_Coro::run_loop_coro() {
    loop_running.store(true, std::memory_order_release);
    try {
        co_await loop_coro();
        loop_running.store(false, std::memory_order_release);
        co_return;
    }
    catch (const std::exception& e) {
        loop_running.store(false, std::memory_order_release);
        auto str = std::format("{} loop_coro 异常退出: {}\n", key, Psc::platform_2_utf8(e.what()));
        record_exception(str);
        std::cerr << str;
        set_state(State::Loop_Exception, str);
        throw;
    }
    catch (...) {
        loop_running.store(false, std::memory_order_release);
        record_exception("loop_coro unknown exception");
        set_state(State::Loop_Exception, "loop_coro unknown exception");
        throw;
    }
}
asio::awaitable<void> With_Loop_Coro::tick() {
    std::string name = type + ":" + key;
    const auto current_state = state.load();
    if (current_state == State::Force_Quit) {
        static Frequency_Limit_Multi flm;
        if (flm.test(name)) {
            std::cout << std::format("{} 正在强制退出!\n", name);
        }
    }
    if (current_state == State::Start) {
        if (enabled()) {
            set_state(State::Before_Request_Start_Loop);
        }
    }
    else if (current_state == State::Before_Request_Start_Loop) {
        co_await this->_open();
        loop_running = enabled();
        auto future = asio::co_spawn(Coro::instance()->io, run_loop_coro(), asio::use_future);
        loop_task = std::make_shared<std::future<void>>(std::move(future));
        //loop_task = Coro::instance()->spawn(run_loop_coro());
        // loop_task = asio::co_spawn(Coro::instance()->io, run_loop_coro(), [](std::exception_ptr exception) {
        // 	if (exception) {
        // 		std::cout << " 发生了异常！" << std::endl;
        // 		std::rethrow_exception(exception);
        // 	}
        // });
        set_state(State::Waiting_Loop_Start, "开始启动任务");
    }
    else if (current_state == State::Waiting_Loop_Start) {
        if (running()) {
            set_state(State::Loop_Running, "启动任务成功！");
        }
    }
    else if (current_state == State::Loop_Running) {
        if (!enabled()) {
            set_state(State::Before_Request_Stop_Loop, std::format("{} 检测到 enable变化 异步退出开始！", name));
        }
    }
    else if (current_state == State::Loop_Exception) {
        bool catch_exception = false;
        if (!catch_exception) {
            loop_task->get();
        }
        else {
            std::exception_ptr task_exception;
            try {
                // 走到这里直接崩溃
                loop_task->get();
            }
            catch (...) {
                task_exception = std::current_exception();
            }
            loop_task.reset();
            co_await _close();
            if (task_exception) {
                loop_running = false;
                try {
                    std::rethrow_exception(task_exception);
                }
                catch (const std::exception& e) {
                    std::cout << std::format("任务异常退出 {}! {}\n", name, e.what()) << std::flush;
                }
                catch (...) {
                    std::cout << std::format("任务未知异常退出 {}!\n", name) << std::flush;
                }
                set_state(State::Start, "任务异常退出");
                co_return;
            }
            else {
                std::cout << "没有异常  状态机 紊乱" << std::endl;
                std::terminate();
            }
            co_return;
        }
    }
    else if (current_state == State::Before_Request_Stop_Loop) {
        loop_running = false;
        set_state(State::Waiting_Stop_Loop, "退出变量已设置  等待退出");
    }
    else if (current_state == State::Waiting_Stop_Loop) {
        if (!running()) {
            loop_task.reset();
            co_await this->_close();
            set_state(State::Start, "任务正常退出");
        }
    }
    co_return;
}
