namespace DodoSSH.Client.Session.Tests;

/// <summary>
/// Where the profile goes.
/// </summary>
/// <remarks>
/// A short suite for something that looks trivial and is not. The cache is a SQLite file written by one
/// process, and the design assumes each machine has its own — the outbox holds changes only this machine
/// has made. Two machines sharing one file through a cloud sync client corrupts it, so a roaming or
/// synced directory is a correctness problem rather than a matter of taste.
/// </remarks>
public sealed class ClientPathsTests
{
    [Fact]
    public void TheCacheLivesInsideTheProfileDirectory()
    {
        var paths = new ClientPaths(Path.Combine("C:", "somewhere", "DodoSSH"));

        Path.GetDirectoryName(paths.CacheFile).ShouldBe(paths.DataDirectory);
        Path.GetFileName(paths.CacheFile).ShouldBe("cache.db");
    }

    [Fact]
    public void TheDefaultDirectoryIsAbsoluteAndNamed()
    {
        var paths = ClientPaths.Default;

        Path.IsPathFullyQualified(paths.DataDirectory).ShouldBeTrue(paths.DataDirectory);

        // OrdinalIgnoreCase, and the casing is the point rather than an oversight. ClientPaths spells the
        // folder DodoSSH on Windows and dodossh on Unix on purpose — one follows the platform's title-cased
        // convention, the other the lower-case dotfile one. The Ordinal "odoSSH" this used to look for was
        // clever enough to survive either spelling of the leading D and still only ever matched Windows,
        // which went unnoticed for exactly as long as nothing ran the suite anywhere else.
        paths.DataDirectory.Contains("dodossh", StringComparison.OrdinalIgnoreCase)
            .ShouldBeTrue($"'{paths.DataDirectory}' should be identifiable as ours");
    }

    [Fact]
    public void ResolvingTheDefault_CreatesNothing()
    {
        // Read during startup diagnostics and by tests. A side effect here would mean merely asking where
        // the cache would go creates a directory.
        var paths = new ClientPaths(
            Path.Combine(Path.GetTempPath(), $"dodossh-paths-{Guid.CreateVersion7():N}"));

        Directory.Exists(paths.DataDirectory).ShouldBeFalse();

        paths.EnsureCreated();

        try
        {
            Directory.Exists(paths.DataDirectory).ShouldBeTrue();

            // Idempotent, because startup runs it every launch.
            paths.EnsureCreated();
        }
        finally
        {
            Directory.Delete(paths.DataDirectory, recursive: true);
        }
    }

    [Fact]
    public void OnWindowsItIsTheLocalProfileAndNotTheRoamingOne()
    {
        // %APPDATA% roams in a domain environment, which would sync one machine's SQLite cache to another
        // and corrupt it. %LOCALAPPDATA% does not.
        if (!OperatingSystem.IsWindows())
        {
            Assert.Skip("Windows-only path convention.");
        }

        var local = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
        var roaming = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);

        ClientPaths.Default.DataDirectory.ShouldStartWith(local);

        // Guard against the two happening to be equal on some configuration, which would make the
        // assertion above meaningless.
        if (!string.Equals(local, roaming, StringComparison.OrdinalIgnoreCase))
        {
            ClientPaths.Default.DataDirectory.ShouldNotStartWith(roaming);
        }
    }
}
