using MarketAlly.AIPlugin; using MarketAlly.AIPlugin.Analysis.Plugins; using Microsoft.Extensions.Logging; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Reflection; using System.Threading.Tasks; namespace MarketAlly.AIPlugin.Analysis.Infrastructure { /// /// Service for discovering and loading analysis plugins /// public class PluginDiscoveryService : IPluginDiscovery { private readonly ILogger? _logger; public PluginDiscoveryService(ILogger? logger = null) { _logger = logger; } public Task> DiscoverPluginsAsync(string pluginDirectory) { _logger?.LogInformation("Discovering plugins in directory: {PluginDirectory}", pluginDirectory); var plugins = new List(); if (!Directory.Exists(pluginDirectory)) { _logger?.LogWarning("Plugin directory does not exist: {PluginDirectory}", pluginDirectory); return Task.FromResult>(plugins); } var assemblyFiles = Directory.GetFiles(pluginDirectory, "*.dll", SearchOption.AllDirectories); foreach (var assemblyFile in assemblyFiles) { try { var assembly = Assembly.LoadFrom(assemblyFile); var pluginTypes = assembly.GetTypes() .Where(t => typeof(IAIPlugin).IsAssignableFrom(t) && !t.IsInterface && !t.IsAbstract); foreach (var pluginType in pluginTypes) { try { var plugin = Activator.CreateInstance(pluginType) as IAIPlugin; if (plugin != null && ValidatePlugin(plugin)) { plugins.Add(plugin); _logger?.LogDebug("Loaded plugin: {PluginType} from {AssemblyFile}", pluginType.Name, assemblyFile); } } catch (Exception ex) { _logger?.LogError(ex, "Failed to create instance of plugin type: {PluginType}", pluginType.Name); } } } catch (Exception ex) { _logger?.LogError(ex, "Failed to load assembly: {AssemblyFile}", assemblyFile); } } _logger?.LogInformation("Discovered {PluginCount} plugins", plugins.Count); return Task.FromResult>(plugins); } public Task LoadPluginAsync(string assemblyPath, string typeName) { _logger?.LogInformation("Loading specific plugin: {TypeName} from {AssemblyPath}", typeName, assemblyPath); if (!File.Exists(assemblyPath)) { throw new FileNotFoundException($"Assembly file not found: {assemblyPath}"); } var assembly = Assembly.LoadFrom(assemblyPath); var pluginType = assembly.GetType(typeName); if (pluginType == null) { throw new TypeLoadException($"Type not found: {typeName}"); } if (!typeof(IAIPlugin).IsAssignableFrom(pluginType)) { throw new InvalidOperationException($"Type does not implement IAIPlugin: {typeName}"); } var plugin = Activator.CreateInstance(pluginType) as IAIPlugin; if (plugin == null) { throw new InvalidOperationException($"Failed to create instance of type: {typeName}"); } if (!ValidatePlugin(plugin)) { throw new InvalidOperationException($"Plugin validation failed: {typeName}"); } _logger?.LogInformation("Successfully loaded plugin: {TypeName}", typeName); return Task.FromResult(plugin); } public IEnumerable GetBuiltInPlugins() { _logger?.LogInformation("Getting built-in analysis plugins"); var plugins = new List { new PerformanceAnalyzerPlugin(), new ArchitectureValidatorPlugin(), new TechnicalDebtPlugin(), new ComplexityAnalyzerPlugin(), new TestAnalysisPlugin(), new BehaviorAnalysisPlugin(), new SQLiteSchemaReaderPlugin() }; _logger?.LogInformation("Loaded {PluginCount} built-in plugins", plugins.Count); return plugins; } public bool ValidatePlugin(IAIPlugin plugin) { if (plugin == null) { _logger?.LogWarning("Plugin is null"); return false; } try { // Check if plugin has required attributes var pluginType = plugin.GetType(); var aiPluginAttribute = pluginType.GetCustomAttribute(); if (aiPluginAttribute == null) { _logger?.LogWarning("Plugin missing AIPluginAttribute: {PluginType}", pluginType.Name); return false; } // Check if SupportedParameters is implemented if (plugin.SupportedParameters == null) { _logger?.LogWarning("Plugin SupportedParameters is null: {PluginType}", pluginType.Name); return false; } // Validate that ExecuteAsync method exists and is properly implemented var executeMethod = pluginType.GetMethod("ExecuteAsync"); if (executeMethod == null) { _logger?.LogWarning("Plugin missing ExecuteAsync method: {PluginType}", pluginType.Name); return false; } _logger?.LogDebug("Plugin validation successful: {PluginType}", pluginType.Name); return true; } catch (Exception ex) { _logger?.LogError(ex, "Plugin validation failed: {PluginType}", plugin.GetType().Name); return false; } } } }