using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Codex.Dal;
using Codex.Dal.Enums;
using Microsoft.EntityFrameworkCore;
using OpenHarbor.CQRS.Abstractions;

namespace Codex.CQRS.Queries;

/// <summary>
/// Get detailed agent execution by ID
/// </summary>
public record GetAgentExecutionQuery
{
    /// <summary>Execution ID</summary>
    public Guid Id { get; init; }
}

/// <summary>
/// Detailed agent execution information
/// </summary>
public record AgentExecutionDetails
{
    /// <summary>Unique execution identifier</summary>
    public Guid Id { get; init; }

    /// <summary>Agent identifier</summary>
    public Guid AgentId { get; init; }

    /// <summary>Agent name</summary>
    public string AgentName { get; init; } = string.Empty;

    /// <summary>Conversation identifier if part of a conversation</summary>
    public Guid? ConversationId { get; init; }

    /// <summary>Full user prompt</summary>
    public string UserPrompt { get; init; } = string.Empty;

    /// <summary>Additional input context or parameters</summary>
    public string? Input { get; init; }

    /// <summary>Agent's complete output/response</summary>
    public string Output { get; init; } = string.Empty;

    /// <summary>Execution status</summary>
    public ExecutionStatus Status { get; init; }

    /// <summary>Execution start timestamp</summary>
    public DateTime StartedAt { get; init; }

    /// <summary>Execution completion timestamp</summary>
    public DateTime? CompletedAt { get; init; }

    /// <summary>Execution time in milliseconds</summary>
    public long? ExecutionTimeMs { get; init; }

    /// <summary>Input tokens consumed</summary>
    public int? InputTokens { get; init; }

    /// <summary>Output tokens generated</summary>
    public int? OutputTokens { get; init; }

    /// <summary>Total tokens used</summary>
    public int? TotalTokens { get; init; }

    /// <summary>Estimated cost in USD</summary>
    public decimal? EstimatedCost { get; init; }

    /// <summary>Tool calls made during execution (JSON array)</summary>
    public string? ToolCalls { get; init; }

    /// <summary>Tool execution results (JSON array)</summary>
    public string? ToolCallResults { get; init; }

    /// <summary>Error message if execution failed</summary>
    public string? ErrorMessage { get; init; }
}

public class GetAgentExecutionQueryHandler : IQueryHandler<GetAgentExecutionQuery, AgentExecutionDetails?>
{
    private readonly CodexDbContext _dbContext;

    public GetAgentExecutionQueryHandler(CodexDbContext dbContext)
    {
        _dbContext = dbContext;
    }

    public async Task<AgentExecutionDetails?> HandleAsync(
        GetAgentExecutionQuery query,
        CancellationToken cancellationToken = default)
    {
        return await _dbContext.AgentExecutions
            .AsNoTracking()
            .Where(e => e.Id == query.Id)
            .Select(e => new AgentExecutionDetails
            {
                Id = e.Id,
                AgentId = e.AgentId,
                AgentName = e.Agent.Name,
                ConversationId = e.ConversationId,
                UserPrompt = e.UserPrompt,
                Input = e.Input,
                Output = e.Output,
                Status = e.Status,
                StartedAt = e.StartedAt,
                CompletedAt = e.CompletedAt,
                ExecutionTimeMs = e.ExecutionTimeMs,
                InputTokens = e.InputTokens,
                OutputTokens = e.OutputTokens,
                TotalTokens = e.TotalTokens,
                EstimatedCost = e.EstimatedCost,
                ToolCalls = e.ToolCalls,
                ToolCallResults = e.ToolCallResults,
                ErrorMessage = e.ErrorMessage
            })
            .FirstOrDefaultAsync(cancellationToken);
    }
}
