#pragma once

#include <string>
#include <set>
#include <map>
#include <nlohmann/json.hpp>
#include <httplib.h>

#include "EnvConfig.h"
#include "AuthHandler.h"

namespace CppModelBase
{
    typedef std::set<std::string> SimulationNamesListType;
    typedef std::string AgentInfoType;
    typedef nlohmann::json InputDataType;
    typedef nlohmann::json ParameterDataType;
    typedef nlohmann::json ResultDataType;
    typedef nlohmann::json SimulationDataType;

    class ApiConnector
    {
    private:
        EnvConfig config;
        AuthHandler auth;

        std::string hostname = "";
        std::string lastResolvedToken = "";

        void ResolveHostname();
        void LogOfflineState();

    public:
        ApiConnector();
        ApiConnector(Environment env);
        ~ApiConnector();
        std::string GetHostname();
        unsigned int GetPort();
        std::string GetApiKey();
        std::string Login();

        // System
        nlohmann::json GetVersion();

        // Agent
        nlohmann::json GetAgent();
        nlohmann::json SendAgentCommand(const std::string &command);

        // Simulations
        nlohmann::json GetSimulations(const std::string &scope = "user", int limit = 50, int offset = 0);
        nlohmann::json GetSimulationData(const std::string &simulationId);
        void DeleteSimulation(const std::string &simulationId);

        // Simulation inputs
        nlohmann::json GetSimulationInputs(const std::string &simulationId);
        void PostSimulationInputs(const std::string &simulationId, const nlohmann::json &inputs);

        // Executions
        nlohmann::json GetExecutions(const std::string &simulationId, int limit = 50, int offset = 0);
        nlohmann::json PostExecution(const std::string &simulationId, const nlohmann::json &data);
        nlohmann::json GetExecution(const std::string &simulationId, const std::string &executionId);

        // Project generation
        nlohmann::json GenerateProject(const nlohmann::json &request);

        // Users
        nlohmann::json GetUsers(int limit = 50, int offset = 0);
        nlohmann::json CreateUser(const std::string &email, const std::string &role);
        nlohmann::json GetUser(const std::string &userId);
        nlohmann::json UpdateUser(const std::string &userId, const std::string &role);
        void DeleteUser(const std::string &userId);

        Environment GetEnvironment() const;
        bool IsOffline() const;

        // Deprecated — kept for backwards compatibility
        SimulationNamesListType GetSimulationNames();
        SimulationDataType GetSimulationPreexecutionData(const std::string &simulationName);
        void PutSimulationData(const std::string &simulationName, SimulationDataType &simulationData);
    };
}
