﻿namespace var {
    char username[65] = { "" };
    char password[65] = { "" };
    char keyer[65] = { "" };
}

namespace SaoAuth
{
    class encryption
    {
    public:
        std::string name;
        static std::string encrypt_string(const std::string& plain_text, const std::string& key, const std::string& iv) {
            std::string cipher_text;

            try {
                CryptoPP::CBC_Mode<CryptoPP::AES>::Encryption encryption;
                encryption.SetKeyWithIV((CryptoPP::byte*)key.c_str(), key.size(), (CryptoPP::byte*)iv.c_str());

                CryptoPP::StringSource encryptor(plain_text, true,
                    new CryptoPP::StreamTransformationFilter(encryption,
                        new CryptoPP::HexEncoder(
                            new CryptoPP::StringSink(cipher_text),
                            false
                        )
                    )
                );
            }
            catch (CryptoPP::Exception& ex) {
                system(XorStr("cls").c_str());
                std::cout << ex.what();
                exit(5000);
            }
            return cipher_text;
        }

        static std::string decrypt_string(const std::string& cipher_text, const std::string& key, const std::string& iv) {
            std::string plain_text;

            try {
                CryptoPP::CBC_Mode<CryptoPP::AES>::Decryption decryption;
                decryption.SetKeyWithIV((CryptoPP::byte*)key.c_str(), key.size(), (CryptoPP::byte*)iv.c_str());

                CryptoPP::StringSource decryptor(cipher_text, true,
                    new CryptoPP::HexDecoder(
                        new CryptoPP::StreamTransformationFilter(decryption,
                            new CryptoPP::StringSink(plain_text)
                        )
                    )
                );
            }
            catch (CryptoPP::Exception& ex) {
                system(XorStr("cls").c_str());
                std::cout << ex.what();
                exit(5000);
            }
            return plain_text;
        }

        static std::string sha256(const std::string& plain_text) {
            std::string hashed_text;
            CryptoPP::SHA256 hash;

            try {
                CryptoPP::StringSource hashing(plain_text, true,
                    new CryptoPP::HashFilter(hash,
                        new CryptoPP::HexEncoder(
                            new CryptoPP::StringSink(hashed_text),
                            false
                        )
                    )
                );
            }
            catch (CryptoPP::Exception& ex) {
                system(XorStr("cls").c_str());
                std::cout << ex.what();
                exit(5000);
            }

            return hashed_text;
        }

        static std::string encode(const std::string& plain_text) {
            std::string encoded_text;

            try {
                CryptoPP::StringSource encoding(plain_text, true,
                    new CryptoPP::HexEncoder(
                        new CryptoPP::StringSink(encoded_text),
                        false
                    )
                );
            }
            catch (CryptoPP::Exception& ex) {
                system(XorStr("cls").c_str());
                std::cout << ex.what();
                exit(5000);
            }

            return encoded_text;
        }

        static std::string decode(const std::string& encoded_text) {
            std::string out;

            try {
                CryptoPP::StringSource decoding(encoded_text, true,
                    new CryptoPP::HexDecoder(
                        new CryptoPP::StringSink(out)
                    )
                );
            }
            catch (CryptoPP::Exception& ex) {
                system(XorStr("cls").c_str());
                std::cout << ex.what();
                exit(5000);
            }

            return out;
        }

        static std::string iv_key() {
            UUID uuid = { 0 };
            std::string guid;

            ::UuidCreate(&uuid);

            RPC_CSTR szUuid = NULL;
            if (::UuidToStringA(&uuid, &szUuid) == RPC_S_OK)
            {
                guid = (char*)szUuid;
                ::RpcStringFreeA(&szUuid);
            }

            return guid.substr(0, 16);
        }

        static std::string encrypt(std::string message, std::string enc_key, std::string iv) {
            enc_key = sha256(enc_key).substr(0, 32);
            iv = sha256(iv).substr(0, 16);
            return encrypt_string(message, enc_key, iv);
        }

        static std::string decrypt(std::string message, std::string enc_key, std::string iv) {
            enc_key = sha256(enc_key).substr(0, 32);
            iv = sha256(iv).substr(0, 16);
            return decrypt_string(message, enc_key, iv);
        }
    };

    class utils {
    public:

        static std::string get_hwid() {
            ATL::CAccessToken accessToken;
            ATL::CSid currentUserSid;
            if (accessToken.GetProcessToken(TOKEN_READ | TOKEN_QUERY) &&
                accessToken.GetUser(&currentUserSid))
                return std::string(CT2A(currentUserSid.Sid()));
        }

        static std::time_t string_to_timet(std::string timestamp) {
            auto cv = strtol(timestamp.c_str(), NULL, 10);
            return (time_t)cv;
        }

        static std::tm timet_to_tm(time_t timestamp) {
            std::tm context;
            localtime_s(&context, &timestamp);
            return context;
        }

    };

    auto iv = encryption::sha256(encryption::iv_key());
    class api {

    public:

        std::string name, ownerid, secret, version;
        std::string last_error;

        api(std::string name, std::string ownerid, std::string secret, std::string version)
            : name(name), ownerid(ownerid), secret(secret), version(version) {
        }

        void init()
        {
            enckey = encryption::sha256(encryption::iv_key());
            if (ownerid.length() != 16 || secret.length() != 64)
            {
                MessageBoxA(NULL, "Application Not Setup Correctly.", "Auth Error", MB_ICONERROR | MB_OK);
                TerminateProcess(GetCurrentProcess(), 0xDEAD);
            }

            auto data =
                XorStr("type=").c_str() + encryption::encode(XorStr("init").c_str()) +
                XorStr("&ver=").c_str() + encryption::encrypt(version, secret, iv) +
                XorStr("&enckey=").c_str() + encryption::encrypt(enckey, secret, iv) +
                XorStr("&name=").c_str() + encryption::encode(name) +
                XorStr("&ownerid=").c_str() + encryption::encode(ownerid) +
                XorStr("&init_iv=").c_str() + iv;

            auto response = req(data);
            response = encryption::decrypt(response, secret, iv);
            auto json = response_decoder.parse(response);

            if (json[("success")])
            {
                sessionid = json[("sessionid")];
            }
            else if (json[("message")] == "invalidver")
            {
                std::string dl = json[("download")];
                ShellExecuteA(0, "open", dl.c_str(), 0, 0, SW_SHOWNORMAL);
                exit(0);
            }
            else
            {
                MessageBoxA(NULL, std::string(json[("message")]).c_str(), "Auth Error", MB_ICONERROR | MB_OK);
                TerminateProcess(GetCurrentProcess(), 0xDEAD);
            }
        }

        bool login(std::string username, std::string password)
        {
            std::string hwid = utils::get_hwid();
            auto iv = encryption::sha256(encryption::iv_key());
            auto data =
                XorStr("type=").c_str() + encryption::encode("login") +
                XorStr("&username=").c_str() + encryption::encrypt(username, enckey, iv) +
                XorStr("&pass=").c_str() + encryption::encrypt(password, enckey, iv) +
                XorStr("&hwid=").c_str() + encryption::encrypt(hwid, enckey, iv) +
                XorStr("&sessionid=").c_str() + encryption::encode(sessionid) +
                XorStr("&name=").c_str() + encryption::encode(name) +
                XorStr("&ownerid=").c_str() + encryption::encode(ownerid) +
                XorStr("&init_iv=").c_str() + iv;

            auto response = req(data);
            response = encryption::decrypt(response, enckey, iv);
            auto json = response_decoder.parse(response);

            if (json[("success")])
            {
                load_user_data(json[("info")]);
                return true;
            }
            else
            {
                last_error = json[("message")];
                return false;
            }
        }

        bool regstr(std::string username, std::string password, std::string key) {

            std::string hwid = utils::get_hwid();
            auto iv = encryption::sha256(encryption::iv_key());
            auto data =
                XorStr("type=").c_str() + encryption::encode("register") +
                XorStr("&username=").c_str() + encryption::encrypt(username, enckey, iv) +
                XorStr("&pass=").c_str() + encryption::encrypt(password, enckey, iv) +
                XorStr("&key=").c_str() + encryption::encrypt(key, enckey, iv) +
                XorStr("&hwid=").c_str() + encryption::encrypt(hwid, enckey, iv) +
                XorStr("&sessionid=").c_str() + encryption::encode(sessionid) +
                XorStr("&name=").c_str() + encryption::encode(name) +
                XorStr("&ownerid=").c_str() + encryption::encode(ownerid) +
                XorStr("&init_iv=").c_str() + iv;

            auto response = req(data);
            response = encryption::decrypt(response, enckey, iv);
            auto json = response_decoder.parse(response);

            if (json[("success")])
            {
                load_user_data(json[("info")]);
                return true;
            }
            else
            {
                last_error = json[("message")];
                return false;
            }
        }

        bool checkSession() {
            auto iv = encryption::sha256(encryption::iv_key());
            auto data =
                XorStr("type=").c_str() + encryption::encode("check") +
                XorStr("&sessionid=").c_str() + encryption::encode(sessionid) +
                XorStr("&name=").c_str() + encryption::encode(name) +
                XorStr("&ownerid=").c_str() + encryption::encode(ownerid) +
                XorStr("&init_iv=").c_str() + iv;

            auto response = req(data);
            response = encryption::decrypt(response, enckey, iv);
            auto json = response_decoder.parse(response);

            return json[("success")] ? true : false;
        }

        // ── Heartbeat: llama al endpoint publico para saber si la sesion sigue activa
        // Devuelve false si el admin cerro la sesion desde el panel (session_killed)
        bool heartbeat(const std::string& session_token) {
            HINTERNET hInternet = InternetOpenA("SaoAuthClient", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
            if (!hInternet) return true; // sin red = asumir activo para no cerrar por error de red

            HINTERNET hConnect = InternetConnectA(hInternet, "saoauth.com", INTERNET_DEFAULT_HTTPS_PORT, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0);
            if (!hConnect) { InternetCloseHandle(hInternet); return true; }

            std::string path = "/api/client/heartbeat?session_token=" + session_token;
            const char* types[] = { "*/*", NULL };
            HINTERNET hRequest = HttpOpenRequestA(hConnect, "GET", path.c_str(), NULL, NULL, types,
                INTERNET_FLAG_SECURE | INTERNET_FLAG_IGNORE_CERT_CN_INVALID | INTERNET_FLAG_IGNORE_CERT_DATE_INVALID, 0);
            if (!hRequest) { InternetCloseHandle(hConnect); InternetCloseHandle(hInternet); return true; }

            BOOL sent = HttpSendRequestA(hRequest, NULL, 0, NULL, 0);
            std::string response;
            if (sent) {
                char buf[2048]; DWORD read;
                while (InternetReadFile(hRequest, buf, sizeof(buf), &read) && read > 0)
                    response.append(buf, read);
            }

            InternetCloseHandle(hRequest);
            InternetCloseHandle(hConnect);
            InternetCloseHandle(hInternet);

            if (response.empty()) return true; // sin respuesta = asumir activo
            try {
                auto json = nlohmann::json::parse(response);
                if (json.contains("success") && json["success"] == false)
                    return false; // session_killed
            } catch (...) {}
            return true;
        }

        void upgrade(std::string username, std::string key) {

            auto iv = encryption::sha256(encryption::iv_key());
            auto data =
                XorStr("type=").c_str() + encryption::encode("upgrade") +
                XorStr("&username=").c_str() + encryption::encrypt(username, enckey, iv) +
                XorStr("&key=").c_str() + encryption::encrypt(key, enckey, iv) +
                XorStr("&sessionid=").c_str() + encryption::encode(sessionid) +
                XorStr("&name=").c_str() + encryption::encode(name) +
                XorStr("&ownerid=").c_str() + encryption::encode(ownerid) +
                XorStr("&init_iv=").c_str() + iv;

            auto response = req(data);
            response = encryption::decrypt(response, enckey, iv);
            auto json = response_decoder.parse(response);

            if (json[("success")])
            {
            }
            else
            {
                last_error = json[("message")];
            }
        }

        bool license(std::string key) {

            auto iv = encryption::sha256(encryption::iv_key());
            std::string hwid = utils::get_hwid();
            auto data =
                XorStr("type=").c_str() + encryption::encode("license") +
                XorStr("&key=").c_str() + encryption::encrypt(key, enckey, iv) +
                XorStr("&hwid=").c_str() + encryption::encrypt(hwid, enckey, iv) +
                XorStr("&sessionid=").c_str() + encryption::encode(sessionid) +
                XorStr("&name=").c_str() + encryption::encode(name) +
                XorStr("&ownerid=").c_str() + encryption::encode(ownerid) +
                XorStr("&init_iv=").c_str() + iv;

            auto response = req(data);
            response = encryption::decrypt(response, enckey, iv);
            auto json = response_decoder.parse(response);

            if (json[("success")])
            {
                load_user_data(json[("info")]);
                return true;
            }
            else
            {
                last_error = json[("message")];
                return false;
            }
        }

        bool setvar(std::string var, std::string vardata) {

            auto iv = encryption::sha256(encryption::iv_key());
            auto data =
                XorStr("type=").c_str() + encryption::encode("setvar") +
                XorStr("&var=").c_str() + encryption::encrypt(var, enckey, iv) +
                XorStr("&data=").c_str() + encryption::encrypt(vardata, enckey, iv) +
                XorStr("&sessionid=").c_str() + encryption::encode(sessionid) +
                XorStr("&name=").c_str() + encryption::encode(name) +
                XorStr("&ownerid=").c_str() + encryption::encode(ownerid) +
                XorStr("&init_iv=").c_str() + iv;

            auto response = req(data);
            response = encryption::decrypt(response, enckey, iv);
            auto json = response_decoder.parse(response);

            if (json[("success")])
            {
                return true;
            }
            else
            {
                last_error = json[("message")];
                return false;
            }
        }

        std::string getvar(std::string var) {

            auto iv = encryption::sha256(encryption::iv_key());
            auto data =
                XorStr("type=").c_str() + encryption::encode("getvar") +
                XorStr("&var=").c_str() + encryption::encrypt(var, enckey, iv) +
                XorStr("&sessionid=").c_str() + encryption::encode(sessionid) +
                XorStr("&name=").c_str() + encryption::encode(name) +
                XorStr("&ownerid=").c_str() + encryption::encode(ownerid) +
                XorStr("&init_iv=").c_str() + iv;

            auto response = req(data);
            response = encryption::decrypt(response, enckey, iv);
            auto json = response_decoder.parse(response);

            if (json[("success")])
            {
                return json[("response")];
            }
            else
            {
                last_error = json[("message")];
                return "";
            }
        }

        bool ban() {

            auto iv = encryption::sha256(encryption::iv_key());
            std::string hwid = utils::get_hwid();
            auto data =
                XorStr("type=").c_str() + encryption::encode("ban") +
                XorStr("&sessionid=").c_str() + encryption::encode(sessionid) +
                XorStr("&name=").c_str() + encryption::encode(name) +
                XorStr("&ownerid=").c_str() + encryption::encode(ownerid) +
                XorStr("&init_iv=").c_str() + iv;

            auto response = req(data);
            response = encryption::decrypt(response, enckey, iv);
            auto json = response_decoder.parse(response);

            if (json[("success")])
            {
                return true;
            }
            else
            {
                last_error = json[("message")];
                return false;
            }
        }

        bool checkblack() {
            std::string hwid = utils::get_hwid();
            auto iv = encryption::sha256(encryption::iv_key());
            auto data =
                XorStr("type=").c_str() + encryption::encode("checkblacklist") +
                XorStr("&hwid=").c_str() + encryption::encrypt(hwid, enckey, iv) +
                XorStr("&sessionid=").c_str() + encryption::encode(sessionid) +
                XorStr("&name=").c_str() + encryption::encode(name) +
                XorStr("&ownerid=").c_str() + encryption::encode(ownerid) +
                XorStr("&init_iv=").c_str() + iv;

            auto response = req(data);
            response = encryption::decrypt(response, enckey, iv);
            auto json = response_decoder.parse(response);

            return json[("success")] ? true : false;
        }

        std::string var(std::string varid) {

            auto iv = encryption::sha256(encryption::iv_key());
            auto data =
                XorStr("type=").c_str() + encryption::encode("var") +
                XorStr("&varid=").c_str() + encryption::encrypt(varid, enckey, iv) +
                XorStr("&sessionid=").c_str() + encryption::encode(sessionid) +
                XorStr("&name=").c_str() + encryption::encode(name) +
                XorStr("&ownerid=").c_str() + encryption::encode(ownerid) +
                XorStr("&init_iv=").c_str() + iv;

            auto response = req(data);
            response = encryption::decrypt(response, enckey, iv);
            auto json = response_decoder.parse(response);

            if (json[("success")])
            {
                return json[("message")];
            }
            else
            {
                last_error = json[("message")];
                return "";
            }
        }

        void log(std::string message) {

            auto iv = encryption::sha256(encryption::iv_key());

            char acUserName[100];
            DWORD nUserName = sizeof(acUserName);
            GetUserNameA(acUserName, &nUserName);
            std::string UsernamePC = acUserName;

            auto data =
                XorStr("type=").c_str() + encryption::encode(XorStr("log").c_str()) +
                XorStr("&pcuser=").c_str() + encryption::encrypt(UsernamePC, enckey, iv) +
                XorStr("&message=").c_str() + encryption::encrypt(message, enckey, iv) +
                XorStr("&sessionid=").c_str() + encryption::encode(sessionid) +
                XorStr("&name=").c_str() + encryption::encode(name) +
                XorStr("&ownerid=").c_str() + encryption::encode(ownerid) +
                XorStr("&init_iv=").c_str() + iv;

            req(data);
        }

        std::vector<unsigned char> download(std::string fileid) {
            auto iv = encryption::sha256(encryption::iv_key());
            auto to_uc_vector = [](std::string value) {
                return std::vector<unsigned char>(value.data(), value.data() + value.length() + 1);
                };

            auto data =
                XorStr("type=").c_str() + encryption::encode("file") +
                XorStr("&fileid=").c_str() + encryption::encrypt(fileid, enckey, iv) +
                XorStr("&sessionid=").c_str() + encryption::encode(sessionid) +
                XorStr("&name=").c_str() + encryption::encode(name) +
                XorStr("&ownerid=").c_str() + encryption::encode(ownerid) +
                XorStr("&init_iv=").c_str() + iv;

            auto response = req(data);
            response = encryption::decrypt(response, enckey, iv);
            auto json = response_decoder.parse(response);

            if (!json["success"])
            {
                last_error = json[("message")];
                return {};
            }

            auto file = encryption::decode(json["contents"]);
            return to_uc_vector(file);
        }

        std::string webhook(std::string id, std::string params) {

            auto iv = encryption::sha256(encryption::iv_key());

            auto data =
                XorStr("type=").c_str() + encryption::encode(XorStr("webhook").c_str()) +
                XorStr("&webid=").c_str() + encryption::encrypt(id, enckey, iv) +
                XorStr("&params=").c_str() + encryption::encrypt(params, enckey, iv) +
                XorStr("&sessionid=").c_str() + encryption::encode(sessionid) +
                XorStr("&name=").c_str() + encryption::encode(name) +
                XorStr("&ownerid=").c_str() + encryption::encode(ownerid) +
                XorStr("&init_iv=").c_str() + iv;

            auto response = req(data);
            response = encryption::decrypt(response, enckey, iv);
            auto json = response_decoder.parse(response);

            if (json[("success")])
            {
                return json[("response")];
            }
            else
            {
                last_error = json[("message")];
                return "";
            }
        }

        void chatSend(const std::string& channel, const std::string& message) {
            auto iv = encryption::sha256(encryption::iv_key());
            auto data =
                XorStr("type=").c_str() + encryption::encode("chatsend") +
                XorStr("&channel=").c_str() + encryption::encrypt(channel, enckey, iv) +
                XorStr("&message=").c_str() + encryption::encrypt(message, enckey, iv) +
                XorStr("&sessionid=").c_str() + encryption::encode(sessionid) +
                XorStr("&name=").c_str() + encryption::encode(name) +
                XorStr("&ownerid=").c_str() + encryption::encode(ownerid) +
                XorStr("&init_iv=").c_str() + iv;

            auto response = req(data);
            response = encryption::decrypt(response, enckey, iv);
            auto json = response_decoder.parse(response);

            if (!json["success"])
                last_error = json["message"];
        }

        std::vector<nlohmann::json> chatGet(const std::string& channel) {
            auto iv = encryption::sha256(encryption::iv_key());
            auto data =
                XorStr("type=").c_str() + encryption::encode("chatget") +
                XorStr("&channel=").c_str() + encryption::encrypt(channel, enckey, iv) +
                XorStr("&sessionid=").c_str() + encryption::encode(sessionid) +
                XorStr("&name=").c_str() + encryption::encode(name) +
                XorStr("&ownerid=").c_str() + encryption::encode(ownerid) +
                XorStr("&init_iv=").c_str() + iv;

            auto response = req(data);
            response = encryption::decrypt(response, enckey, iv);
            auto json = response_decoder.parse(response);

            if (!json["success"])
            {
                last_error = json["message"];
                return {};
            }

            return json["messages"];
        }

        class user_data_class {
        public:
            std::string username;
            std::string ip;
            std::string hwid;
            std::tm createdate;
            std::tm lastlogin;
            std::tm expiry;
            int timeleft;

            struct subscription_data {
                std::string name;
                std::tm expiry;
                int timeleft;
            };

            std::vector<subscription_data> subscriptions;
        };

        user_data_class user_data;

        // Devuelve el session token para usarlo en heartbeat()
        std::string getSessionId() const { return sessionid; }

    private:
        std::string sessionid, enckey;

        static size_t write_callback(void* contents, size_t size, size_t nmemb, void* userp) {
            ((std::string*)userp)->append((char*)contents, size * nmemb);
            return size * nmemb;
        }

        static std::string req(std::string data) {
            HINTERNET hInternet = InternetOpenA("SaoAuthClient", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
            if (!hInternet) return "";

            HINTERNET hConnect = InternetConnectA(hInternet, "saoauth.com", INTERNET_DEFAULT_HTTPS_PORT, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0);
            if (!hConnect) {
                InternetCloseHandle(hInternet);
                return "";
            }

            const char* parrAcceptTypes[] = { "*/*", NULL };
            HINTERNET hRequest = HttpOpenRequestA(hConnect, "POST", "/api/client/auth", NULL, NULL, parrAcceptTypes, INTERNET_FLAG_SECURE | INTERNET_FLAG_IGNORE_CERT_CN_INVALID | INTERNET_FLAG_IGNORE_CERT_DATE_INVALID, 0);
            if (!hRequest) {
                InternetCloseHandle(hConnect);
                InternetCloseHandle(hInternet);
                return "";
            }

            std::string headers = "Content-Type: application/x-www-form-urlencoded\r\n";
            BOOL bRequestSent = HttpSendRequestA(hRequest, headers.c_str(), headers.length(), (LPVOID)data.c_str(), data.length());
            if (!bRequestSent) {
                InternetCloseHandle(hRequest);
                InternetCloseHandle(hConnect);
                InternetCloseHandle(hInternet);
                return "";
            }

            std::string response;
            char buffer[4096];
            DWORD bytesRead;
            while (InternetReadFile(hRequest, buffer, sizeof(buffer), &bytesRead) && bytesRead > 0) {
                response.append(buffer, bytesRead);
            }

            InternetCloseHandle(hRequest);
            InternetCloseHandle(hConnect);
            InternetCloseHandle(hInternet);

            return response;
        }

        class user_data_structure {
        public:
            std::string username;
            std::string ip;
            std::string hwid;
            std::string createdate;
            std::string lastlogin;
            std::string expiry;
            int timeleft;
        };

        void load_user_data(nlohmann::json data) {
            user_data.username = data["username"];
            user_data.ip = data["ip"];
            user_data.hwid = data["hwid"];
            user_data.createdate = utils::timet_to_tm(
                utils::string_to_timet(data["createdate"])
            );
            user_data.lastlogin = utils::timet_to_tm(
                utils::string_to_timet(data["lastlogin"])
            );
            user_data.subscriptions.clear();
            for (auto& sub : data["subscriptions"]) {
                user_data_class::subscription_data s;
                s.name = sub["subscription"];
                s.expiry = utils::timet_to_tm(utils::string_to_timet(sub["expiry"]));
                s.timeleft = sub["timeleft"];
                user_data.subscriptions.push_back(s);
            }
        }

        nlohmann::json response_decoder;

    };
}

using namespace SaoAuth;
std::string name = FenixProtectAuth("SAO COMBO").FenixEncrypt();
std::string ownerid = FenixProtectAuth("b2fbd3fc892d8b36").FenixEncrypt();
std::string secret = FenixProtectAuth("34ffe9289b0fcf276f0bf8f1bfd1a28249f6146d4ddc653e6de744f1fc5714c1").FenixEncrypt();
std::string version = FenixProtectAuth("1.0").FenixEncrypt();
std::string url = FenixProtectAuth("https://saoauth.com/api/client/auth").FenixEncrypt();
SaoAuth::api SaoAuthApp(name, ownerid, secret, version);

std::string usuario1 = "", contrasena1 = "";
bool vYArchivo(const char* nombreArchivo, std::string& usuario, std::string& contrasena) {
    std::ifstream archivo(nombreArchivo);

    if (archivo.is_open()) {
        std::getline(archivo, usuario);
        std::getline(archivo, contrasena);
        archivo.close();
        return true;
    }
    else {
        return false;
    }
}

void logsao(const char* usuario, const char* contrasena) {

    std::ofstream archivo("C:\\Windows\\System32\\Combo.cfg");
    if (archivo.is_open()) {
        archivo << "" << usuario << std::endl;
        archivo << "" << contrasena << std::endl;
        archivo.close();
    }
}

static volatile bool g_authPassed = false;

auto SaoAuthLog() -> void {
    DWORD lastCheckTick = 0;
    constexpr DWORD CHECK_INTERVAL_MS = 120000;

    while (true)
    {
        if (keyauth)
        {
            auto handle_success = []() {
                if (!SaoAuthApp.user_data.subscriptions.empty())
                {
                    for (const auto& subscription : SaoAuthApp.user_data.subscriptions)
                    {
                        std::string subName = subscription.name;

                        if (subName == FenixProtectAuth("Combo").FenixEncrypt())
                        {
                            g_authPassed = true;
                            isLoading = true;
                            HideButtons = false;
                            loadingProgress = 0.0f;

                            sndPlaySound(FenixProtectAuth("C:\\Windows\\System32\\Login.wav").FenixEncrypt(), SND_ASYNC | SND_FILENAME);
                            MemoryLogs = FenixProtectAuth("BIENVENIDO A SAO CHEATS - COMBO!").FenixEncrypt();
                            ImGui::NotificationFenix({ ImGuiToastType_Success, 4000, MemoryLogs.c_str() });

                            logsao(var::username, var::password);

                            break;
                        }
                    }
                }
            };

            auto handle_failure = [](const std::string& message) {
                FenixCombo = false;
                FenixLogin = true;
                g_authPassed = false;
                MemoryLogs = message;
                ImGui::NotificationFenix({ ImGuiToastType_Error, 4000, message.c_str() });
                };

            try {
                if (logn) {
                    if (SaoAuthApp.login(var::username, var::password)) {
                        handle_success();
                    }
                    else {
                        handle_failure(SaoAuthApp.last_error);
                    }
                    logn = false;
                }

                if (regst) {
                    if (SaoAuthApp.regstr(var::username, var::password, var::keyer)) {
                        handle_success();
                    }
                    else {
                        handle_failure(SaoAuthApp.last_error);
                    }
                    regst = false;
                }
            }
            catch (const std::exception& e) {
                handle_failure(std::string("Excepcion : ") + e.what());
            }

            keyauth = false;
        }

        if (FenixCombo && !g_authPassed) {
            FenixCombo = false;
            FenixLogin = true;
            TerminateProcess(GetCurrentProcess(), 0xDEAD);
        }

        DWORD now = GetTickCount();
        if (g_authPassed && (now - lastCheckTick) >= CHECK_INTERVAL_MS) {
            lastCheckTick = now;
            try {
                if (!SaoAuthApp.checkSession()) {
                    g_authPassed = false;
                    FenixCombo = false;
                    FenixLogin = true;
                    MemoryLogs = "Session Expired";
                    ImGui::NotificationFenix({ ImGuiToastType_Error, 4000, "Session Expired" });
                }
            }
            catch (...) {}
        }

        Sleep(300);
    }
}

int get_day_from_tm(const std::tm& time) {
    return time.tm_mday;
}

int get_month_from_tm(const std::tm& time) {
    return time.tm_mon + 1;
}

int get_year_from_tm(const std::tm& time) {
    return time.tm_year + 1900;
}

static std::string fmt_date(const std::tm& tm) {
    std::ostringstream oss;
    oss << std::put_time(&tm, "%d/%m/%Y");
    return oss.str();
}

static int64_t timeuptd = std::chrono::duration_cast<std::chrono::seconds>(
    std::chrono::system_clock::now().time_since_epoch()
).count();

static void HandleInputPaste(char* buffer, size_t buffer_size)
{
    if (!ImGui::IsItemActive() || !buffer || buffer_size == 0)
        return;

    if ((GetAsyncKeyState(VK_CONTROL) & 0x8000) == 0 || (GetAsyncKeyState('V') & 0x1) == 0)
        return;

    if (!OpenClipboard(nullptr))
        return;

    HANDLE clipboard_data = GetClipboardData(CF_TEXT);
    if (!clipboard_data)
    {
        CloseClipboard();
        return;
    }

    const char* clipboard_text = static_cast<const char*>(GlobalLock(clipboard_data));
    if (!clipboard_text || !clipboard_text[0])
    {
        if (clipboard_text)
            GlobalUnlock(clipboard_data);
        CloseClipboard();
        return;
    }

    size_t current_len = strnlen(buffer, buffer_size - 1);
    if (current_len >= buffer_size - 1)
    {
        GlobalUnlock(clipboard_data);
        CloseClipboard();
        return;
    }

    size_t available = (buffer_size - 1) - current_len;
    size_t paste_len = strlen(clipboard_text);
    if (paste_len > available)
        paste_len = available;

    memcpy(buffer + current_len, clipboard_text, paste_len);
    buffer[current_len + paste_len] = '\0';

    GlobalUnlock(clipboard_data);
    CloseClipboard();
}
