using Nexus.Api.Models;

namespace Nexus.Api.Services;

public interface IAgentProposalService
{
    Task<AgentCreateOptionsDto> GetCreateOptionsAsync(
        CancellationToken cancellationToken = default);

    Task<AgentProposalCollectionDto> GetAsync(
        int limit = 50,
        string? cursor = null,
        string? status = null,
        CancellationToken cancellationToken = default);

    Task<AgentProposalDto?> GetByIdAsync(
        Guid id,
        bool includeFileContent = true,
        CancellationToken cancellationToken = default);

    Task<AgentProposalOperationDto> CreateAsync(
        CreateAgentProposalRequest request,
        string source,
        OpenClawInvocationMetadata invocation,
        CancellationToken cancellationToken = default);

    Task<AgentProposalOperationDto> ApproveAsync(
        Guid id,
        AgentProposalActionRequest request,
        OpenClawInvocationMetadata invocation,
        CancellationToken cancellationToken = default);

    Task<AgentProposalOperationDto> RejectAsync(
        Guid id,
        AgentProposalActionRequest request,
        OpenClawInvocationMetadata invocation,
        CancellationToken cancellationToken = default);

    Task<AgentProposalOperationDto> RetryAsync(
        Guid id,
        AgentProposalActionRequest request,
        OpenClawInvocationMetadata invocation,
        CancellationToken cancellationToken = default);

    /// <summary>
    /// Converts requests left at a dispatch boundary by a prior process into a
    /// conservative state. It never calls agents.create.
    /// </summary>
    Task RecoverInterruptedRequestsAsync(
        CancellationToken cancellationToken = default);

    /// <summary>
    /// Processes at most one explicitly queued request. Returns false when no
    /// work was available.
    /// </summary>
    Task<bool> ProcessNextAsync(CancellationToken cancellationToken = default);
}

public sealed class AgentProposalValidationException(
    string field,
    string message) : Exception(message)
{
    public string Field { get; } = field;
}
