using System.Reflection;
using ColaFlow.Modules.Mcp.Contracts.Resources;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;

namespace ColaFlow.Modules.Mcp.Application.Services;

/// <summary>
/// Implementation of Resource Discovery Service
/// Scans assemblies to find all IMcpResource implementations
/// </summary>
public class ResourceDiscoveryService : IResourceDiscoveryService
{
    private readonly ILogger<ResourceDiscoveryService> _logger;

    public ResourceDiscoveryService(ILogger<ResourceDiscoveryService> logger)
    {
        _logger = logger;
    }

    public IReadOnlyList<Type> DiscoverResourceTypes()
    {
        _logger.LogInformation("Starting MCP Resource discovery via Assembly scanning...");

        var resourceTypes = new List<Type>();

        // Get all loaded assemblies
        var assemblies = AppDomain.CurrentDomain.GetAssemblies()
            .Where(a => !a.IsDynamic && a.FullName != null && a.FullName.StartsWith("ColaFlow"))
            .ToList();

        _logger.LogDebug("Scanning {Count} assemblies for IMcpResource implementations", assemblies.Count);

        foreach (var assembly in assemblies)
        {
            try
            {
                var types = assembly.GetTypes()
                    .Where(t => typeof(IMcpResource).IsAssignableFrom(t)
                                && !t.IsInterface
                                && !t.IsAbstract
                                && t.IsClass)
                    .ToList();

                if (types.Any())
                {
                    _logger.LogDebug("Found {Count} resources in assembly {Assembly}",
                        types.Count, assembly.GetName().Name);
                    resourceTypes.AddRange(types);
                }
            }
            catch (ReflectionTypeLoadException ex)
            {
                _logger.LogWarning(ex, "Failed to load types from assembly {Assembly}", assembly.FullName);
            }
        }

        _logger.LogInformation("Discovered {Count} MCP Resource types", resourceTypes.Count);

        return resourceTypes.AsReadOnly();
    }

    public IReadOnlyList<IMcpResource> DiscoverAndInstantiateResources(IServiceProvider serviceProvider)
    {
        var resourceTypes = DiscoverResourceTypes();
        var resources = new List<IMcpResource>();

        foreach (var resourceType in resourceTypes)
        {
            try
            {
                // Use DI to instantiate the resource (resolves dependencies automatically)
                var resource = ActivatorUtilities.CreateInstance(serviceProvider, resourceType) as IMcpResource;

                if (resource != null)
                {
                    resources.Add(resource);
                    _logger.LogDebug("Instantiated resource: {ResourceType} -> {Uri}",
                        resourceType.Name, resource.Uri);
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Failed to instantiate resource type {ResourceType}", resourceType.FullName);
            }
        }

        _logger.LogInformation("Instantiated {Count} MCP Resources", resources.Count);

        return resources.AsReadOnly();
    }
}
