using System;
using System.Linq;

using Nitride.Entities;
using Nitride.IO.Contents;
using Nitride.IO.Paths;
using Nitride.Tests;

using Xunit;
using Xunit.Abstractions;

using Zio;

namespace Nitride.IO.Tests;

public class LinkDirectChildrenTests : NitrideIOTestBase
{
    public LinkDirectChildrenTests(ITestOutputHelper output)
        : base(output)
    {
    }

    [Fact]
    public void NestedLinkTest()
    {
        // Set up the test.
        using NitrideIOTestContext context = this.CreateContext();

        // Set up the file.
        IFileSystem fileSystem = context.FileSystem;

        fileSystem.CreateDirectory("/a");
        fileSystem.CreateDirectory("/b");
        fileSystem.CreateDirectory("/a/c");
        fileSystem.CreateDirectory("/a/d");
        fileSystem.CreateDirectory("/a/d/e");
        fileSystem.CreateFile("/index.md");
        fileSystem.CreateFile("/a/index.md");
        fileSystem.CreateFile("/b/index.md");
        fileSystem.CreateFile("/a/c/index.md");
        fileSystem.CreateFile("/a/d/index.md");
        fileSystem.CreateFile("/a/d/e/index.md");

        // Set up the operation.
        ReadFiles readFiles = context.Resolve<ReadFiles>();
        DirectChildPathScanner scanner = context.Resolve<DirectChildPathScanner>();

        CreateOrUpdateIndex op = context.Resolve<LinkDirectChildren>()
            .WithScanner(scanner);

        // Read and replace the paths.
        Tuple<string, string[]?>[]? actual = readFiles.WithPattern("/**")
            .Run()
            .Run(scanner)
            .ToList()
            .Run(op)
            .Select(
                x => new Tuple<string, string[]?>(
                    x.Get<UPath>()
                        .ToString(),
                    x.GetOptional<DirectChildEntityList>()
                        ?.Select(
                            y => y.Get<UPath>()
                                .ToString())
                        .OrderBy(y => y)
                        .ToArray()))
            .OrderBy(x => x.Item1)
            .ToArray();

        // Verify the results.
        Tuple<string, string[]?>[] expected = new[]
        {
            new Tuple<string, string[]?>("/a/c/index.md", new string[] { }),
            new Tuple<string, string[]?>("/a/d/e/index.md", new string[] { }),
            new Tuple<string, string[]?>("/a/d/index.md", new[] { "/a/d/e/index.md" }),
            new Tuple<string, string[]?>("/a/index.md", new[] { "/a/c/index.md", "/a/d/index.md" }),
            new Tuple<string, string[]?>("/b/index.md", new string[] { }),
            new Tuple<string, string[]?>("/index.md", new[] { "/a/index.md", "/b/index.md" }),
        };

        TestHelper.CompareObjects(expected, actual);
    }
}