using System.Text.Json;
using ColaFlow.Modules.Mcp.Contracts.Resources;
using ColaFlow.Modules.ProjectManagement.Application.Common.Interfaces;
using ColaFlow.Modules.ProjectManagement.Domain.Repositories;
using ColaFlow.Modules.ProjectManagement.Domain.ValueObjects;
using Microsoft.Extensions.Logging;

namespace ColaFlow.Modules.Mcp.Application.Resources;

/// <summary>
/// Resource: colaflow://issues.search
/// Searches issues with filters (Epics, Stories, Tasks)
/// Query params: status, priority, assignee, type, project, limit, offset
/// </summary>
public class IssuesSearchResource(
    IProjectRepository projectRepository,
    ITenantContext tenantContext,
    ILogger<IssuesSearchResource> logger)
    : IMcpResource
{
    public string Uri => "colaflow://issues.search";
    public string Name => "Issues Search";
    public string Description => "Search issues with filters (status, priority, assignee, etc.)";
    public string MimeType => "application/json";
    public string Category => "Issues";
    public string Version => "1.0";

    public async Task<McpResourceContent> GetContentAsync(
        McpResourceRequest request,
        CancellationToken cancellationToken)
    {
        var tenantId = tenantContext.GetCurrentTenantId();

        logger.LogDebug("Searching issues for tenant {TenantId} with filters: {@Filters}",
            tenantId, request.QueryParams);

        // Parse query parameters
        var projectFilter = request.QueryParams.GetValueOrDefault("project");
        var statusFilter = request.QueryParams.GetValueOrDefault("status");
        var priorityFilter = request.QueryParams.GetValueOrDefault("priority");
        var typeFilter = request.QueryParams.GetValueOrDefault("type")?.ToLower();
        var assigneeFilter = request.QueryParams.GetValueOrDefault("assignee");
        var limit = int.TryParse(request.QueryParams.GetValueOrDefault("limit"), out var l) ? l : 100;
        var offset = int.TryParse(request.QueryParams.GetValueOrDefault("offset"), out var o) ? o : 0;

        // Limit max results
        limit = Math.Min(limit, 100);

        // Get all projects
        var projects = await projectRepository.GetAllProjectsReadOnlyAsync(cancellationToken);

        // Filter by project if specified
        if (!string.IsNullOrEmpty(projectFilter) && Guid.TryParse(projectFilter, out var projectIdGuid))
        {
            var projectId = ProjectId.From(projectIdGuid);
            var project = await projectRepository.GetProjectWithFullHierarchyReadOnlyAsync(projectId, cancellationToken);
            projects = project != null ? new List<ProjectManagement.Domain.Aggregates.ProjectAggregate.Project> { project } : new();
        }
        else
        {
            // Load full hierarchy for all projects
            var projectsWithHierarchy = new List<ProjectManagement.Domain.Aggregates.ProjectAggregate.Project>();
            foreach (var p in projects)
            {
                var fullProject = await projectRepository.GetProjectWithFullHierarchyReadOnlyAsync(p.Id, cancellationToken);
                if (fullProject != null)
                {
                    projectsWithHierarchy.Add(fullProject);
                }
            }
            projects = projectsWithHierarchy;
        }

        // Collect all issues (Epics, Stories, Tasks)
        var allIssues = new List<object>();

        foreach (var project in projects)
        {
            if (project.Epics == null) continue;

            foreach (var epic in project.Epics)
            {
                // Filter Epics
                if (ShouldIncludeIssue("epic", typeFilter, epic.Status.ToString(), statusFilter,
                    epic.Priority.ToString(), priorityFilter, null, assigneeFilter))
                {
                    allIssues.Add(new
                    {
                        id = epic.Id.Value,
                        type = "Epic",
                        name = epic.Name,
                        description = epic.Description,
                        status = epic.Status.ToString(),
                        priority = epic.Priority.ToString(),
                        projectId = project.Id.Value,
                        projectName = project.Name,
                        createdAt = epic.CreatedAt,
                        storyCount = epic.Stories?.Count ?? 0
                    });
                }

                // Filter Stories
                if (epic.Stories != null)
                {
                    foreach (var story in epic.Stories)
                    {
                        if (ShouldIncludeIssue("story", typeFilter, story.Status.ToString(), statusFilter,
                            story.Priority.ToString(), priorityFilter, story.AssigneeId?.Value.ToString(), assigneeFilter))
                        {
                            allIssues.Add(new
                            {
                                id = story.Id.Value,
                                type = "Story",
                                title = story.Title,
                                description = story.Description,
                                status = story.Status.ToString(),
                                priority = story.Priority.ToString(),
                                assigneeId = story.AssigneeId?.Value,
                                projectId = project.Id.Value,
                                projectName = project.Name,
                                epicId = epic.Id.Value,
                                epicName = epic.Name,
                                createdAt = story.CreatedAt,
                                taskCount = story.Tasks?.Count ?? 0
                            });
                        }

                        // Filter Tasks
                        if (story.Tasks != null)
                        {
                            foreach (var task in story.Tasks)
                            {
                                if (ShouldIncludeIssue("task", typeFilter, task.Status.ToString(), statusFilter,
                                    task.Priority.ToString(), priorityFilter, task.AssigneeId?.Value.ToString(), assigneeFilter))
                                {
                                    allIssues.Add(new
                                    {
                                        id = task.Id.Value,
                                        type = "Task",
                                        title = task.Title,
                                        description = task.Description,
                                        status = task.Status.ToString(),
                                        priority = task.Priority.ToString(),
                                        assigneeId = task.AssigneeId?.Value,
                                        projectId = project.Id.Value,
                                        projectName = project.Name,
                                        storyId = story.Id.Value,
                                        storyTitle = story.Title,
                                        epicId = epic.Id.Value,
                                        epicName = epic.Name,
                                        createdAt = task.CreatedAt
                                    });
                                }
                            }
                        }
                    }
                }
            }
        }

        // Apply pagination
        var total = allIssues.Count;
        var paginatedIssues = allIssues.Skip(offset).Take(limit).ToList();

        var json = JsonSerializer.Serialize(new
        {
            issues = paginatedIssues,
            total = total,
            limit = limit,
            offset = offset
        }, new JsonSerializerOptions { WriteIndented = true });

        logger.LogInformation("Found {Count} issues for tenant {TenantId} (total: {Total})",
            paginatedIssues.Count, tenantId, total);

        return new McpResourceContent
        {
            Uri = Uri,
            MimeType = MimeType,
            Text = json
        };
    }

    private bool ShouldIncludeIssue(
        string issueType,
        string? typeFilter,
        string status,
        string? statusFilter,
        string priority,
        string? priorityFilter,
        string? assigneeId,
        string? assigneeFilter)
    {
        // Type filter
        if (!string.IsNullOrEmpty(typeFilter) && !issueType.Equals(typeFilter, StringComparison.OrdinalIgnoreCase))
        {
            return false;
        }

        // Status filter
        if (!string.IsNullOrEmpty(statusFilter) && !status.Equals(statusFilter, StringComparison.OrdinalIgnoreCase))
        {
            return false;
        }

        // Priority filter
        if (!string.IsNullOrEmpty(priorityFilter) && !priority.Equals(priorityFilter, StringComparison.OrdinalIgnoreCase))
        {
            return false;
        }

        // Assignee filter
        if (!string.IsNullOrEmpty(assigneeFilter) && assigneeId != assigneeFilter)
        {
            return false;
        }

        return true;
    }
}
