#include "PythonEngine.h"
#include <pybind11/embed.h>
#include <filesystem>
#include <iostream>
#include <SDL2/SDL_log.h>
#include <thread>
#include <chrono>

namespace py = pybind11;
namespace fs = std::filesystem;

PythonEngine& PythonEngine::Get()
{
    static PythonEngine instance;
    return instance;
}

void PythonEngine::Init()
{
    if (initialized_)
    {
        SDL_Log("[Python] Already initialized");
        return;
    }
    
    py::initialize_interpreter();
    
    try
    {
        auto sys = py::module_::import("sys");
        sys.attr("path").attr("append")(".");
        sys.attr("path").attr("append")("scripts");
        sys.attr("path").attr("append")("assets/scripts");
        SDL_Log("[Python] scripts paths added");
        
        // Load modules
        py::module_::import("states");
    }
    catch (...)
    {
        SDL_Log("[Python] Warning: Failed to update sys.path ");
    }
    
    // Release GIL immidiately so game loop can run freely
    PyEval_SaveThread();
    
    initialized_ = true;
    SDL_Log("[Python] Embedded interpreter ready (managed by scoped_interpreter)");
}

void PythonEngine::Shutdown()
{
    if (initialized_) { return; }
    
    StopAutoReload();
    
    PyEval_RestoreThread(PyGILState_GetThisThreadState());
    py::finalize_interpreter();
    initialized_ = false;
}

void PythonEngine::Exec(const std::string& code)
{
    py::gil_scoped_acquire gil;
    
    try
    {
        py::exec(code);
    }
    catch (const py::error_already_set& e)
    {
        SDL_Log("[Python] Error: %s", e.what());
    }
    catch (const std::exception& e)
    {
        SDL_Log("[Python] Error: %s", e.what());
    }
}

// Reload single module
bool PythonEngine::ReloadModule(const std::string& module_name)
{
    py::gil_scoped_acquire gil;
    try
    {
        auto importlib = py::module_::import("importlib");
        auto sys = py::module_::import("sys");
        
        if (py::hasattr(sys, "modules") && py::hasattr(sys.attr("modules"), module_name.c_str()))
        {
            auto module = sys.attr("modules")[module_name.c_str()];
            importlib.attr("reload")(module);
            SDL_Log("[Python] Reloaded module: %s", module_name.c_str());
            return true;
        }
        else // First-time import
        {
            py::module_::import(module_name.c_str());
            SDL_Log("[Python] Imported module: %s", module_name.c_str());
            return true;
        }
    }
    catch (const py::error_already_set& e)
    {
        SDL_Log("[Python] Reload module %s error: %s", module_name.c_str(), e.what());
        return false;
    }
}

void PythonEngine::ReloadAllScripts()
{
    SDL_Log("[Python] Reloading all scripts");
    
    // ReloadModule("main_menu");
    // ReloadModule("player_controller");
    // ...
}

void PythonEngine::StartAutoReload(float intervalSeconds)
{
    if (autoReloadRunning_) { return; }
    
    autoReloadRunning_ = true;
    autoReloadThread_ = std::thread([this, interval = std::chrono::milliseconds(static_cast<int>(intervalSeconds * 1000))]() {
        while (autoReloadRunning_)
        {
            std::this_thread::sleep_for(interval);
            
            py::gil_scoped_acquire gil;
            try
            {
                ReloadAllScripts();
            }
            catch (...)
            {
            }
        }
    });
}

void PythonEngine::StopAutoReload()
{
    if (!autoReloadRunning_) { return; }
    autoReloadRunning_ = false;
    if (autoReloadThread_.joinable())
    {
        autoReloadThread_.join();
    }
}