using System.Text.Json;
using System.Text.RegularExpressions;
using ColaFlow.Modules.Mcp.Application.Services;
using ColaFlow.Modules.Mcp.Contracts.Resources;
using ColaFlow.Modules.Mcp.Domain.Exceptions;
using Microsoft.Extensions.Logging;

namespace ColaFlow.Modules.Mcp.Application.Handlers;

/// <summary>
/// Handler for the 'resources/read' MCP method
/// </summary>
public class ResourcesReadMethodHandler : IMcpMethodHandler
{
    private readonly ILogger<ResourcesReadMethodHandler> _logger;
    private readonly IMcpResourceRegistry _resourceRegistry;

    public string MethodName => "resources/read";

    public ResourcesReadMethodHandler(
        ILogger<ResourcesReadMethodHandler> logger,
        IMcpResourceRegistry resourceRegistry)
    {
        _logger = logger;
        _resourceRegistry = resourceRegistry;
    }

    public async Task<object?> HandleAsync(object? @params, CancellationToken cancellationToken)
    {
        _logger.LogDebug("Handling resources/read request");

        // Parse parameters
        var paramsJson = JsonSerializer.Serialize(@params);
        var request = JsonSerializer.Deserialize<ResourceReadParams>(paramsJson);

        if (request == null || string.IsNullOrWhiteSpace(request.Uri))
        {
            throw new McpInvalidParamsException("Missing required parameter: uri");
        }

        _logger.LogInformation("Reading resource: {Uri}", request.Uri);

        // Find resource by URI
        var resource = _resourceRegistry.GetResourceByUri(request.Uri);
        if (resource == null)
        {
            throw new McpNotFoundException($"Resource not found: {request.Uri}");
        }

        // Parse URI and extract parameters
        var resourceRequest = ParseResourceRequest(request.Uri, resource.Uri);

        // Get resource content
        var content = await resource.GetContentAsync(resourceRequest, cancellationToken);

        // Return MCP response
        var response = new
        {
            contents = new[]
            {
                new
                {
                    uri = content.Uri,
                    mimeType = content.MimeType,
                    text = content.Text
                }
            }
        };

        return response;
    }

    /// <summary>
    /// Parse resource URI and extract path/query parameters
    /// </summary>
    private McpResourceRequest ParseResourceRequest(string requestUri, string templateUri)
    {
        var request = new McpResourceRequest { Uri = requestUri };

        // Split URI and query string
        var uriParts = requestUri.Split('?', 2);
        var path = uriParts[0];
        var queryString = uriParts.Length > 1 ? uriParts[1] : string.Empty;

        // Extract path parameters from template
        // Example: "colaflow://projects.get/123" with template "colaflow://projects.get/{id}"
        var pattern = "^" + Regex.Escape(templateUri)
            .Replace(@"\{", "{")
            .Replace(@"\}", "}")
            .Replace("{id}", @"(?<id>[^/]+)")
            .Replace("{projectId}", @"(?<projectId>[^/]+)")
            + "$";

        var match = Regex.Match(path, pattern);
        if (match.Success)
        {
            foreach (Group group in match.Groups)
            {
                if (!int.TryParse(group.Name, out _) && group.Name != "0")
                {
                    request.UriParams[group.Name] = group.Value;
                }
            }
        }

        // Parse query parameters
        if (!string.IsNullOrEmpty(queryString))
        {
            var queryPairs = queryString.Split('&');
            foreach (var pair in queryPairs)
            {
                var keyValue = pair.Split('=', 2);
                if (keyValue.Length == 2)
                {
                    request.QueryParams[keyValue[0]] = Uri.UnescapeDataString(keyValue[1]);
                }
            }
        }

        return request;
    }

    private class ResourceReadParams
    {
        public string Uri { get; set; } = string.Empty;
    }
}
