using System.Reflection;
using Inspectron.Settings;
using Ninject;
using Serilog;
using VisionBuilder.UI.Common.Attributes;

namespace VisionBuilder.UI.Common.Plugins;

[ModulePriority(1000)]
public class PluginLoader:IVisionBuilderModule
{
    

    const string PLUGINS_DIRECTORY = "Plugins";

    public List<IPlugin> Plugins { get; } = new List<IPlugin>();

    private bool _isInitialized;



    private string _pluginsProfile = "enabled_plugins.txt";

    public void InitializeModule(string? pluginsProfile)
    {
        if (pluginsProfile != null)
            _pluginsProfile = pluginsProfile + ".txt";
        InitializeModule();
    }

    public void InitializeModule()
    {
        if (_isInitialized)
        {
            return;
        }

        _isInitialized = true;
        Log.Information("Loading plugins...");
        var pluginsPath = Path.Combine("..", "Data", PLUGINS_DIRECTORY);

        var enabledPluginsPath = Path.Combine(pluginsPath, _pluginsProfile);
        if (!File.Exists(enabledPluginsPath))
        {
            Log.Warning("Enabled plugins file not found: {EnabledPluginsPath}. All discovered plugins will be disabled by default.", enabledPluginsPath);
             File.WriteAllText(enabledPluginsPath, "");
        }

        List<string> enabledPlugins = File.ReadAllLines(enabledPluginsPath).ToList();
        Directory.CreateDirectory(pluginsPath);
        var pluginFolders = Directory.GetDirectories(pluginsPath);
        
        foreach (string folder in pluginFolders)
        {
            var pluginName = Path.GetFileNameWithoutExtension(folder);


            if (!enabledPlugins.Contains(pluginName))
            {
                Log.Information("Skipping plugin {PluginName} as it is not enabled in settings.", pluginName);
                continue;
            }
            

            var assemblyPath = Path.Combine(folder, Path.GetFileNameWithoutExtension(folder) + ".dll");

            if (!File.Exists(assemblyPath))
            {
                Log.Warning("Plugin assembly not found: {AssemblyPath}", assemblyPath);
                continue;
            }
            try
            {
                LoadPluginAssembly(assemblyPath);
            }
            catch (Exception ex)
            {
                Log.Error(ex, "Failed to load plugin from {AssemblyPath}", assemblyPath);
            }
        }
        Log.Information("Plugin loading completed.");
    }

    private void LoadPluginAssembly(string assemblyPath)
    {
        var absPath = Path.GetFullPath(assemblyPath);
        var loadContext = new PluginLoadContext(absPath);
        var assembly = loadContext.LoadFromAssemblyPath(absPath);
        Log.Information("Loaded plugin assembly: {AssemblyName}", assembly.GetName().Name);
        foreach (var type in assembly.GetTypes())
        {
            if (type.IsAssignableTo(typeof(IPlugin)) && !type.IsAbstract)
            {
                Plugins.Add((IPlugin)Activator.CreateInstance(type));
                Log.Information("Loaded plugin: {PluginName}", type.FullName);
            }


        }
    }

    
}