using System;
using System.IO;
using System.Threading.Tasks;
using SharepointToolbox.Core.Models;
using SharepointToolbox.Infrastructure.Auth;
using SharepointToolbox.Services;
using Xunit;

namespace SharepointToolbox.Tests.Auth;

[Trait("Category", "Unit")]
public class SessionManagerTests : IDisposable
{
    private readonly string _tempCacheDir;
    private readonly MsalClientFactory _factory;
    private readonly SessionManager _sessionManager;

    public SessionManagerTests()
    {
        _tempCacheDir = Path.Combine(Path.GetTempPath(), "SessionManagerTests_" + Guid.NewGuid());
        Directory.CreateDirectory(_tempCacheDir);
        _factory = new MsalClientFactory(_tempCacheDir);
        _sessionManager = new SessionManager(_factory);
    }

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

    // ── IsAuthenticated ──────────────────────────────────────────────────────

    [Fact]
    public void IsAuthenticated_BeforeAnyAuth_ReturnsFalse()
    {
        Assert.False(_sessionManager.IsAuthenticated("https://contoso.sharepoint.com"));
    }

    [Fact]
    public void IsAuthenticated_NormalizesTrailingSlash()
    {
        Assert.False(_sessionManager.IsAuthenticated("https://contoso.sharepoint.com/"));
        Assert.False(_sessionManager.IsAuthenticated("https://contoso.sharepoint.com"));
    }

    // ── ClearSessionAsync ────────────────────────────────────────────────────

    [Fact]
    public async Task ClearSessionAsync_UnknownTenantUrl_DoesNotThrow()
    {
        // Must be idempotent — no exception for tenants that were never authenticated
        await _sessionManager.ClearSessionAsync("https://unknown.sharepoint.com");
    }

    [Fact]
    public async Task ClearSessionAsync_MultipleCalls_DoNotThrow()
    {
        await _sessionManager.ClearSessionAsync("https://contoso.sharepoint.com");
        await _sessionManager.ClearSessionAsync("https://contoso.sharepoint.com");
    }

    // ── Argument validation ──────────────────────────────────────────────────

    [Fact]
    public async Task GetOrCreateContextAsync_NullTenantUrl_ThrowsArgumentException()
    {
        var profile = new TenantProfile { TenantUrl = null!, ClientId = "clientId", Name = "Test" };
        await Assert.ThrowsAnyAsync<ArgumentException>(
            () => _sessionManager.GetOrCreateContextAsync(profile));
    }

    [Fact]
    public async Task GetOrCreateContextAsync_EmptyTenantUrl_ThrowsArgumentException()
    {
        var profile = new TenantProfile { TenantUrl = "", ClientId = "clientId", Name = "Test" };
        await Assert.ThrowsAnyAsync<ArgumentException>(
            () => _sessionManager.GetOrCreateContextAsync(profile));
    }

    [Fact]
    public async Task GetOrCreateContextAsync_NullClientId_ThrowsArgumentException()
    {
        var profile = new TenantProfile { TenantUrl = "https://contoso.sharepoint.com", ClientId = null!, Name = "Test" };
        await Assert.ThrowsAnyAsync<ArgumentException>(
            () => _sessionManager.GetOrCreateContextAsync(profile));
    }

    [Fact]
    public async Task GetOrCreateContextAsync_EmptyClientId_ThrowsArgumentException()
    {
        var profile = new TenantProfile { TenantUrl = "https://contoso.sharepoint.com", ClientId = "", Name = "Test" };
        await Assert.ThrowsAnyAsync<ArgumentException>(
            () => _sessionManager.GetOrCreateContextAsync(profile));
    }

    // ── Interactive login test (skipped — requires MSAL interactive flow) ────

    [Fact(Skip = "Requires interactive MSAL — integration test only")]
    public Task GetOrCreateContextAsync_CreatesContext()
    {
        return Task.CompletedTask;
    }
}
