using System;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using SharepointToolbox.Infrastructure.Auth;
using Xunit;

namespace SharepointToolbox.Tests.Auth;

[Trait("Category", "Unit")]
public class MsalClientFactoryTests : IDisposable
{
    private readonly string _tempCacheDir;

    public MsalClientFactoryTests()
    {
        _tempCacheDir = Path.Combine(Path.GetTempPath(), "MsalClientFactoryTests_" + Guid.NewGuid());
        Directory.CreateDirectory(_tempCacheDir);
    }

    public void Dispose()
    {
        try { Directory.Delete(_tempCacheDir, recursive: true); } catch { /* best effort */ }
    }

    [Fact]
    public async Task GetOrCreateAsync_SameClientId_ReturnsSameInstance()
    {
        var factory = new MsalClientFactory(_tempCacheDir);

        var pca1 = await factory.GetOrCreateAsync("clientA");
        var pca2 = await factory.GetOrCreateAsync("clientA");

        Assert.Same(pca1, pca2);
    }

    [Fact]
    public async Task GetOrCreateAsync_DifferentClientIds_ReturnDifferentInstances()
    {
        var factory = new MsalClientFactory(_tempCacheDir);

        var pcaA = await factory.GetOrCreateAsync("clientA");
        var pcaB = await factory.GetOrCreateAsync("clientB");

        Assert.NotSame(pcaA, pcaB);
    }

    [Fact]
    public async Task GetOrCreateAsync_ConcurrentCalls_DoNotCreateDuplicateInstances()
    {
        var factory = new MsalClientFactory(_tempCacheDir);

        // Run 10 concurrent calls with the same clientId
        var tasks = Enumerable.Range(0, 10)
            .Select(_ => factory.GetOrCreateAsync("clientConcurrent"))
            .ToArray();

        var results = await Task.WhenAll(tasks);

        // All 10 results must be the exact same instance
        var first = results[0];
        Assert.All(results, r => Assert.Same(first, r));
    }

    [Fact]
    public void CacheDirectory_ResolvesToAppData_Not_Hardcoded()
    {
        // The default (no-arg) constructor must use %AppData%\SharepointToolbox\auth
        var factory = new MsalClientFactory();
        var expectedBase = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
        var expectedDir = Path.Combine(expectedBase, "SharepointToolbox", "auth");

        Assert.Equal(expectedDir, factory.CacheDirectory);
    }
}
