using Codex.Dal;
using Codex.Dal.Enums;
using Microsoft.EntityFrameworkCore;

namespace Codex.Api.Endpoints;

/// <summary>
/// Simple, pragmatic REST endpoints for MVP.
/// No over-engineering. Just JSON lists that work.
/// </summary>
public static class SimpleEndpoints
{
    public static WebApplication MapSimpleEndpoints(this WebApplication app)
    {
        // ============================================================
        // AGENTS
        // ============================================================

        app.MapGet("/api/agents", async (CodexDbContext db) =>
        {
            var agents = await db.Agents
                .Where(a => !a.IsDeleted)
                .OrderByDescending(a => a.CreatedAt)
                .Select(a => new
                {
                    a.Id,
                    a.Name,
                    a.Description,
                    a.Type,
                    a.ModelProvider,
                    a.ModelName,
                    a.ProviderType,
                    a.ModelEndpoint,
                    a.Status,
                    a.CreatedAt,
                    a.UpdatedAt,
                    ToolCount = a.Tools.Count(t => t.IsEnabled),
                    ExecutionCount = a.Executions.Count
                })
                .Take(100) // More than enough for MVP
                .ToListAsync();

            return Results.Ok(agents);
        })
        .WithName("GetAllAgents")
        .WithTags("Agents")
        .WithOpenApi(operation =>
        {
            operation.Summary = "Get all agents";
            operation.Description = "Returns a list of all active agents with metadata. Limit: 100 most recent.";
            return operation;
        })
        .Produces<object>(200);

        app.MapGet("/api/agents/{id:guid}/conversations", async (Guid id, CodexDbContext db) =>
        {
            var conversations = await db.AgentExecutions
                .Where(e => e.AgentId == id && e.ConversationId != null)
                .Select(e => e.ConversationId)
                .Distinct()
                .Join(db.Conversations,
                    convId => convId,
                    c => (Guid?)c.Id,
                    (convId, c) => new
                    {
                        c.Id,
                        c.Title,
                        c.Summary,
                        c.StartedAt,
                        c.LastMessageAt,
                        c.MessageCount,
                        c.IsActive
                    })
                .OrderByDescending(c => c.LastMessageAt)
                .ToListAsync();

            return Results.Ok(conversations);
        })
        .WithName("GetAgentConversations")
        .WithTags("Agents")
        .WithOpenApi(operation =>
        {
            operation.Summary = "Get conversations for an agent";
            operation.Description = "Returns all conversations associated with a specific agent.";
            return operation;
        })
        .Produces<object>(200);

        app.MapGet("/api/agents/{id:guid}/executions", async (Guid id, CodexDbContext db) =>
        {
            var executions = await db.AgentExecutions
                .Where(e => e.AgentId == id)
                .OrderByDescending(e => e.StartedAt)
                .Select(e => new
                {
                    e.Id,
                    e.AgentId,
                    e.ConversationId,
                    UserPrompt = e.UserPrompt.Substring(0, Math.Min(e.UserPrompt.Length, 200)), // Truncate for list view
                    e.Status,
                    e.StartedAt,
                    e.CompletedAt,
                    e.InputTokens,
                    e.OutputTokens,
                    e.EstimatedCost,
                    MessageCount = e.Messages.Count,
                    e.ErrorMessage
                })
                .Take(100)
                .ToListAsync();

            return Results.Ok(executions);
        })
        .WithName("GetAgentExecutions")
        .WithTags("Agents")
        .WithOpenApi(operation =>
        {
            operation.Summary = "Get execution history for an agent";
            operation.Description = "Returns the 100 most recent executions for a specific agent.";
            return operation;
        })
        .Produces<object>(200);

        // ============================================================
        // CONVERSATIONS
        // ============================================================

        app.MapGet("/api/conversations", async (CodexDbContext db) =>
        {
            var conversations = await db.Conversations
                .OrderByDescending(c => c.LastMessageAt)
                .Select(c => new
                {
                    c.Id,
                    c.Title,
                    c.Summary,
                    c.StartedAt,
                    c.LastMessageAt,
                    c.MessageCount,
                    c.IsActive,
                    ExecutionCount = db.AgentExecutions.Count(e => e.ConversationId == c.Id)
                })
                .Take(100)
                .ToListAsync();

            return Results.Ok(conversations);
        })
        .WithName("GetAllConversations")
        .WithTags("Conversations")
        .WithOpenApi(operation =>
        {
            operation.Summary = "Get all conversations";
            operation.Description = "Returns the 100 most recent conversations.";
            return operation;
        })
        .Produces<object>(200);

        // ============================================================
        // EXECUTIONS
        // ============================================================

        app.MapGet("/api/executions", async (CodexDbContext db) =>
        {
            var executions = await db.AgentExecutions
                .Include(e => e.Agent)
                .OrderByDescending(e => e.StartedAt)
                .Select(e => new
                {
                    e.Id,
                    e.AgentId,
                    AgentName = e.Agent.Name,
                    e.ConversationId,
                    UserPrompt = e.UserPrompt.Substring(0, Math.Min(e.UserPrompt.Length, 200)),
                    e.Status,
                    e.StartedAt,
                    e.CompletedAt,
                    e.InputTokens,
                    e.OutputTokens,
                    e.EstimatedCost,
                    MessageCount = e.Messages.Count,
                    e.ErrorMessage
                })
                .Take(100)
                .ToListAsync();

            return Results.Ok(executions);
        })
        .WithName("GetAllExecutions")
        .WithTags("Executions")
        .WithOpenApi(operation =>
        {
            operation.Summary = "Get all executions";
            operation.Description = "Returns the 100 most recent executions across all agents.";
            return operation;
        })
        .Produces<object>(200);

        app.MapGet("/api/executions/status/{status}", async (string status, CodexDbContext db) =>
        {
            if (!Enum.TryParse<ExecutionStatus>(status, true, out var executionStatus))
            {
                return Results.BadRequest(new { error = $"Invalid status: {status}. Valid values: Pending, Running, Completed, Failed, Cancelled" });
            }

            var executions = await db.AgentExecutions
                .Include(e => e.Agent)
                .Where(e => e.Status == executionStatus)
                .OrderByDescending(e => e.StartedAt)
                .Select(e => new
                {
                    e.Id,
                    e.AgentId,
                    AgentName = e.Agent.Name,
                    e.ConversationId,
                    UserPrompt = e.UserPrompt.Substring(0, Math.Min(e.UserPrompt.Length, 200)),
                    e.Status,
                    e.StartedAt,
                    e.CompletedAt,
                    e.InputTokens,
                    e.OutputTokens,
                    e.EstimatedCost,
                    MessageCount = e.Messages.Count,
                    e.ErrorMessage
                })
                .Take(100)
                .ToListAsync();

            return Results.Ok(executions);
        })
        .WithName("GetExecutionsByStatus")
        .WithTags("Executions")
        .WithOpenApi(operation =>
        {
            operation.Summary = "Get executions by status";
            operation.Description = "Returns executions filtered by status (Pending, Running, Completed, Failed, Cancelled).";
            return operation;
        })
        .Produces<object>(200)
        .Produces(400);

        return app;
    }
}
