using System.IO;
using ClaudeDo.Installer.Core;

namespace ClaudeDo.Installer.Tests;

public sealed class InstallManifestStoreTests : IDisposable
{
    private readonly string _tempDir;

    public InstallManifestStoreTests()
    {
        _tempDir = Path.Combine(Path.GetTempPath(), "ClaudeDoInstallerTests-" + Guid.NewGuid().ToString("N"));
        Directory.CreateDirectory(_tempDir);
    }

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

    [Fact]
    public void TryRead_ReturnsNull_WhenFileMissing()
    {
        var result = InstallManifestStore.TryRead(_tempDir);
        Assert.Null(result);
    }

    [Fact]
    public void Write_Then_Read_RoundTripsAllFields()
    {
        var manifest = new InstallManifest(
            Version: "0.2.0",
            InstallDir: _tempDir,
            WorkerDir: Path.Combine(_tempDir, "worker"),
            InstalledAt: new DateTimeOffset(2026, 4, 15, 12, 34, 56, TimeSpan.Zero));

        InstallManifestStore.Write(_tempDir, manifest);

        var round = InstallManifestStore.TryRead(_tempDir);
        Assert.NotNull(round);
        Assert.Equal("0.2.0", round!.Version);
        Assert.Equal(manifest.InstallDir, round.InstallDir);
        Assert.Equal(manifest.WorkerDir, round.WorkerDir);
        Assert.Equal(manifest.InstalledAt, round.InstalledAt);
    }

    [Fact]
    public void Write_CreatesInstallDir_IfMissing()
    {
        var nested = Path.Combine(_tempDir, "nested");
        Assert.False(Directory.Exists(nested));

        InstallManifestStore.Write(nested, new InstallManifest(
            "0.0.1", nested, Path.Combine(nested, "worker"), DateTimeOffset.UtcNow));

        Assert.True(File.Exists(Path.Combine(nested, "install.json")));
    }

    [Fact]
    public void TryRead_ReturnsNull_WhenJsonMalformed()
    {
        File.WriteAllText(Path.Combine(_tempDir, "install.json"), "{ not json");
        var result = InstallManifestStore.TryRead(_tempDir);
        Assert.Null(result);
    }

    [Fact]
    public void TryRead_ReturnsNull_WhenJsonIsValidButShapeIsWrong()
    {
        // Valid JSON, but installedAt has a wrong type — causes JsonException, swallowed silently.
        File.WriteAllText(Path.Combine(_tempDir, "install.json"),
            """{"version":"1.0","installDir":"x","workerDir":"y","installedAt":12345}""");
        var result = InstallManifestStore.TryRead(_tempDir);
        Assert.Null(result);
    }
}
