#include "SessionStore.h"
#include <boost/uuid/uuid_generators.hpp>
#include <boost/uuid/uuid_io.hpp>
namespace Older {
SessionStore::SessionStore(boost::asio::io_context &ioContext) : m_ioContext(ioContext), m_cleanupTimer(ioContext) {
    startCleanupTask();
}

std::string SessionStore::addSession(int userId, std::chrono::minutes sessionLifetime, std::chrono::minutes refreshInterval) {
    using namespace boost::uuids;
    using namespace std::chrono;
    std::unique_lock lock(m_mutex);

    random_generator uuid_gen;
    auto now = system_clock::now();

    SessionData data{userId,
                     to_string(uuid_gen()), // 生成刷新令牌
                     now + sessionLifetime, now + refreshInterval};

    std::string access_token = to_string(uuid_gen());
    m_sessions[access_token] = data;

    m_refreshMap[data.refreshToken] = access_token;

    return access_token;
}

void SessionStore::removeSession(const std::string &token) {
    std::unique_lock lock(m_mutex);
    auto it = m_sessions.find(token);
    if (it != m_sessions.end()) {
        m_refreshMap.erase(it->second.refreshToken);
        m_sessions.erase(it);
    }
}

std::pair<bool, std::string> SessionStore::validateAndRefresh(const std::string &token) {
    using namespace std::chrono;
    using namespace boost::uuids;
    std::unique_lock lock(m_mutex);
    auto it = m_sessions.find(token);
    if (it == m_sessions.end()) return {false, ""};

    auto now = system_clock::now();
    SessionData &data = it->second;

    if (now > data.expireTime) { // 检查是否过期
        m_sessions.erase(it);
        m_refreshMap.erase(data.refreshToken);
        return {false, ""};
    }

    std::string newToken = token;
    if (now > data.refreshTime) { // 检查是否需要刷新
        random_generator uuid_gen;
        newToken = to_string(uuid_gen());

        // 保留刷新令牌
        SessionData newData = data;
        newData.refreshTime = now + minutes{15};

        m_sessions.erase(it);
        m_sessions[newToken] = newData;

        m_refreshMap[data.refreshToken] = newToken;
    }

    return {true, newToken};
}

SessionData SessionStore::at(const std::string &token) {
    SessionData ret;
    if (m_sessions.count(token) > 0) {
        ret = m_sessions.at(token);
    }
    return ret;
}

void SessionStore::startCleanupTask() {
    using namespace std::chrono_literals;
    m_cleanupTimer.expires_after(5min);
    m_cleanupTimer.async_wait([this](boost::system::error_code ec) {
        if (!ec) {
            cleanupExpiredSessions();
            startCleanupTask();
        }
    });
}

void SessionStore::cleanupExpiredSessions() {
    using namespace std::chrono;
    std::unique_lock lock(m_mutex);
    auto now = system_clock::now();

    for (auto it = m_sessions.begin(); it != m_sessions.end();) {
        if (now > it->second.expireTime) {
            m_refreshMap.erase(it->second.refreshToken);
            it = m_sessions.erase(it);
        } else {
            ++it;
        }
    }
}

} // namespace Older