using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Nexus.Api.Models;
using Nexus.Api.Services;

namespace Nexus.Api.Controllers;

[Authorize(Roles = "owner")]
[ProducesResponseType(
    typeof(OpenClawAgentConfigurationErrorDto),
    StatusCodes.Status403Forbidden)]
[ProducesResponseType(
    typeof(OpenClawAgentConfigurationErrorDto),
    StatusCodes.Status409Conflict)]
[ProducesResponseType(
    typeof(OpenClawAgentConfigurationErrorDto),
    StatusCodes.Status502BadGateway)]
[ProducesResponseType(
    typeof(OpenClawAgentConfigurationErrorDto),
    StatusCodes.Status503ServiceUnavailable)]
[ProducesResponseType(
    typeof(OpenClawAgentConfigurationErrorDto),
    StatusCodes.Status504GatewayTimeout)]
[ApiController]
[Route("api/v1/memory")]
public class MemoryController(IMemoryService memoryService) : ControllerBase
{
    [HttpGet]
    [ProducesResponseType(typeof(IReadOnlyList<MemoryFileInfo>), StatusCodes.Status200OK)]
    public Task<IResult> GetAll(
        [FromQuery] string agentId = "iris",
        CancellationToken cancellationToken = default)
        => OpenClawContentReadEndpoint.ExecuteAsync(async () =>
            Results.Ok(await memoryService.GetAllAsync(
                agentId,
                cancellationToken)));

    [HttpGet("search")]
    [ProducesResponseType(typeof(IReadOnlyList<MemorySearchResult>), StatusCodes.Status200OK)]
    [ProducesResponseType(typeof(ValidationProblemDetails), StatusCodes.Status400BadRequest)]
    public Task<IResult> Search(
        [FromQuery] string q,
        [FromQuery] string agentId = "iris",
        CancellationToken cancellationToken = default)
    {
        if (string.IsNullOrWhiteSpace(q) || q.Length < 2)
        {
            return Task.FromResult<IResult>(
                Results.ValidationProblem(new Dictionary<string, string[]>
            {
                ["q"] = ["Query must be at least 2 characters."]
            }));
        }

        return OpenClawContentReadEndpoint.ExecuteAsync(async () =>
            Results.Ok(await memoryService.SearchAsync(
                q,
                agentId,
                cancellationToken)));
    }

    [HttpGet("{name}")]
    [ProducesResponseType(typeof(MemoryFileContent), StatusCodes.Status200OK)]
    [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status404NotFound)]
    public Task<IResult> GetFile(
        string name,
        [FromQuery] string agentId = "iris",
        CancellationToken cancellationToken = default)
        => OpenClawContentReadEndpoint.ExecuteAsync(async () =>
        {
            var file = await memoryService.GetFileAsync(
                name,
                agentId,
                cancellationToken);
            return file is null ? Results.NotFound() : Results.Ok(file);
        });
}
