using Nexus.Api.Models;

namespace Nexus.Api.Services;

internal static class OpenClawContentReadHelpers
{
    public const int MaxFiles = 50;
    public const int MaxContentBytes = 1_000_000;
    private const int MaxConcurrency = 4;

    public static async Task<IReadOnlyList<TResult>> SelectBoundedAsync<TSource, TResult>(
        IEnumerable<TSource> source,
        Func<TSource, CancellationToken, Task<TResult?>> selector,
        CancellationToken cancellationToken)
        where TResult : class
    {
        var items = source.Take(MaxFiles).ToArray();
        var results = new TResult?[items.Length];
        await Parallel.ForEachAsync(
            Enumerable.Range(0, items.Length),
            new ParallelOptions
            {
                CancellationToken = cancellationToken,
                MaxDegreeOfParallelism = MaxConcurrency
            },
            async (index, token) =>
            {
                results[index] = await selector(items[index], token);
            });
        return results.Where(item => item is not null).Select(item => item!).ToArray();
    }

    public static string? ReadText(OpenClawWorkspaceFileDto file)
    {
        if (file.Size > MaxContentBytes
            || !string.Equals(file.Encoding, "utf8", StringComparison.OrdinalIgnoreCase)
            || System.Text.Encoding.UTF8.GetByteCount(file.Content) >
               MaxContentBytes)
        {
            return null;
        }

        return file.Content;
    }

    public static bool IsMarkdownFile(OpenClawWorkspaceEntryDto entry)
        => string.Equals(entry.Kind, "file", StringComparison.Ordinal)
           && entry.Path.EndsWith(".md", StringComparison.OrdinalIgnoreCase)
           && (entry.Size is null || entry.Size <= MaxContentBytes);

    public static bool IsNotFound(OpenClawGatewayRpcException exception)
        => exception.Code.Equals("NOT_FOUND", StringComparison.OrdinalIgnoreCase)
           || exception.Code.Equals(
               "FILE_NOT_FOUND",
               StringComparison.OrdinalIgnoreCase)
           || exception.Code.Equals(
               "PATH_NOT_FOUND",
               StringComparison.OrdinalIgnoreCase);

    public static bool IsSafeFileName(string? value)
        => !string.IsNullOrWhiteSpace(value)
           && value.Length <= 240
           && value is not "." and not ".."
           && !value.StartsWith('.')
           && !value.Contains('/')
           && !value.Contains('\\')
           && !value.Contains('\0')
           && !value.Any(char.IsControl);

    public static string LegacyPath(string workspacePath, string prefix)
        => workspacePath.StartsWith(
            prefix + "/",
            StringComparison.OrdinalIgnoreCase)
            ? workspacePath[(prefix.Length + 1)..]
            : workspacePath;
}
