using System.Text.RegularExpressions;
using ColaFlow.Modules.Mcp.Contracts.Resources;
using Microsoft.Extensions.Logging;

namespace ColaFlow.Modules.Mcp.Application.Services;

/// <summary>
/// Implementation of MCP Resource Registry
/// Enhanced with category support and dynamic registration
/// </summary>
public class McpResourceRegistry(ILogger<McpResourceRegistry> logger) : IMcpResourceRegistry
{
    private readonly Dictionary<string, IMcpResource> _resources = new();
    private readonly List<IMcpResource> _resourceList = new();
    private readonly object _lock = new();

    public void RegisterResource(IMcpResource resource)
    {
        lock (_lock)
        {
            if (_resources.ContainsKey(resource.Uri))
            {
                logger.LogWarning("Resource already registered: {Uri}. Overwriting.", resource.Uri);
                _resourceList.Remove(_resources[resource.Uri]);
            }

            _resources[resource.Uri] = resource;
            _resourceList.Add(resource);

            logger.LogInformation("Registered MCP Resource: {Uri} - {Name} [{Category}]",
                resource.Uri, resource.Name, resource.Category);
        }
    }

    public IReadOnlyList<IMcpResource> GetAllResources()
    {
        lock (_lock)
        {
            return _resourceList.AsReadOnly();
        }
    }

    public IMcpResource? GetResourceByUri(string uri)
    {
        lock (_lock)
        {
            // Try exact match first
            if (_resources.TryGetValue(uri, out var resource))
            {
                return resource;
            }

            // Try matching against URI templates (e.g., "colaflow://projects.get/{id}")
            foreach (var registeredResource in _resourceList)
            {
                if (UriMatchesTemplate(uri, registeredResource.Uri))
                {
                    return registeredResource;
                }
            }

            return null;
        }
    }

    public IReadOnlyList<McpResourceDescriptor> GetResourceDescriptors()
    {
        lock (_lock)
        {
            return _resourceList
                .Select(r => r.GetDescriptor())
                .ToList()
                .AsReadOnly();
        }
    }

    /// <summary>
    /// Get resources by category
    /// </summary>
    public IReadOnlyList<IMcpResource> GetResourcesByCategory(string category)
    {
        lock (_lock)
        {
            return _resourceList
                .Where(r => r.Category.Equals(category, StringComparison.OrdinalIgnoreCase))
                .ToList()
                .AsReadOnly();
        }
    }

    /// <summary>
    /// Get all categories
    /// </summary>
    public IReadOnlyList<string> GetCategories()
    {
        lock (_lock)
        {
            return _resourceList
                .Select(r => r.Category)
                .Distinct()
                .OrderBy(c => c)
                .ToList()
                .AsReadOnly();
        }
    }

    /// <summary>
    /// Get resources grouped by category
    /// </summary>
    public IReadOnlyDictionary<string, List<IMcpResource>> GetResourcesGroupedByCategory()
    {
        lock (_lock)
        {
            return _resourceList
                .GroupBy(r => r.Category)
                .ToDictionary(g => g.Key, g => g.ToList())
                .AsReadOnly();
        }
    }

    /// <summary>
    /// Check if a URI matches a URI template
    /// Example: "colaflow://projects.get/123" matches "colaflow://projects.get/{id}"
    /// </summary>
    private bool UriMatchesTemplate(string uri, string template)
    {
        // Convert template to regex pattern
        // Replace {param} with regex group
        var pattern = "^" + Regex.Escape(template)
            .Replace(@"\{", "{")
            .Replace(@"\}", "}")
            .Replace("{id}", @"([^/]+)")
            .Replace("{projectId}", @"([^/]+)")
            + "$";

        return Regex.IsMatch(uri, pattern);
    }
}
