using System.IO;
using JobTrackerApi.Services;
using JobTrackerApi.Tests.TestSupport;
using Microsoft.AspNetCore.DataProtection;
using Xunit;

namespace JobTrackerApi.Tests;

// Regression coverage for the SSRF guard in ImapService: an authenticated user's IMAP "connect"
// target must not be usable to probe loopback/RFC1918/link-local/cloud-metadata addresses.
public sealed class ImapServiceSsrfGuardTests
{
    [Theory]
    [InlineData("127.0.0.1")]
    [InlineData("localhost")]
    [InlineData("10.0.0.5")]
    [InlineData("172.16.0.5")]
    [InlineData("192.168.1.5")]
    [InlineData("169.254.169.254")] // cloud metadata endpoint
    public async Task ConnectAsync_rejects_internal_and_metadata_hosts(string host)
    {
        var service = CreateService();

        var ex = await Assert.ThrowsAsync<InvalidOperationException>(() =>
            service.ConnectAsync("user-1", host, 993, true, "user", "password", CancellationToken.None));

        // Message must not leak connect-vs-auth distinction (that's the oracle this guard closes).
        Assert.DoesNotContain("resolve", ex.Message, StringComparison.OrdinalIgnoreCase);
        Assert.DoesNotContain("reachable", ex.Message, StringComparison.OrdinalIgnoreCase);
    }

    [Fact]
    public async Task ConnectAsync_rejects_unresolvable_host_without_leaking_dns_detail()
    {
        var service = CreateService();

        var ex = await Assert.ThrowsAsync<InvalidOperationException>(() =>
            service.ConnectAsync("user-1", "this-host-does-not-exist.invalid", 993, true, "user", "password", CancellationToken.None));

        Assert.Equal("Could not connect to that IMAP server with the given credentials. Check host, port, and password.", ex.Message);
    }

    private static ImapService CreateService()
    {
        var db = TestHostFactory.CreateInMemoryDb();
        var protectionProvider = DataProtectionProvider.Create(new DirectoryInfo(Path.Combine(Path.GetTempPath(), $"jobtracker-tests-{Guid.NewGuid():N}")));
        return new ImapService(db, protectionProvider);
    }
}
