using System.IO;
using FluentAssertions;
using DragonISO.App.Services;

namespace DragonISO.App.Tests.Services;

// Unit tests for NotesService â€” the append-only show-notes log.
// Uses the DirectoryOverride seam so writes land in a tempdir and
// don't pollute the dev's real %LOCALAPPDATA%\Dragon-ISO\Notes folder.
//
// Shares NotesStateCollection with any sibling class that mutates
// NotesService.DirectoryOverride (the same static-state-shared-via-
// parallel-classes problem the PresetStoreCollection solves).
[Collection(NotesStateCollection.Name)]
public sealed class NotesServiceTests : IDisposable
{
    private readonly string _tempDir;
    private readonly string? _previousOverride;

    public NotesServiceTests()
    {
        _tempDir = Path.Combine(Path.GetTempPath(), $"Dragon-ISO-notes-{Guid.NewGuid():N}");
        _previousOverride = NotesService.DirectoryOverride;
        NotesService.DirectoryOverride = _tempDir;
    }

    public void Dispose()
    {
        NotesService.DirectoryOverride = _previousOverride;
        try { if (Directory.Exists(_tempDir)) Directory.Delete(_tempDir, recursive: true); }
        catch { /* test cleanup is best-effort */ }
    }

    [Fact]
    public void Append_WritesHeaderAndLine_OnFirstCall()
    {
        var ok = NotesService.Append("first note");

        ok.Should().BeTrue();
        File.Exists(NotesService.TodayPath).Should().BeTrue();
        var content = File.ReadAllText(NotesService.TodayPath);
        content.Should().StartWith("# Dragon-ISO show notes â€” ");
        content.Should().Contain("â€” first note");
    }

    [Fact]
    public void Append_PrependsTimestampPrefix_InCanonicalFormat()
    {
        NotesService.Append("checkpoint");

        var content = File.ReadAllText(NotesService.TodayPath);
        // Each appended line follows "- **HH:mm:ss** â€” <text>" so a
        // reader can scan the file as Markdown without preprocessing.
        content.Should().MatchRegex(@"- \*\*\d{2}:\d{2}:\d{2}\*\* â€” checkpoint");
    }

    [Fact]
    public void Append_AppendsAdditionalLines_AfterTheFirst()
    {
        NotesService.Append("alpha");
        NotesService.Append("beta");
        NotesService.Append("gamma");

        var content = File.ReadAllText(NotesService.TodayPath);
        content.Should().Contain("alpha");
        content.Should().Contain("beta");
        content.Should().Contain("gamma");
        // Header written exactly once, not before every line.
        var headerCount = content.Split("# Dragon-ISO show notes â€”").Length - 1;
        headerCount.Should().Be(1);
    }

    [Fact]
    public void Append_TrimsLeadingAndTrailingWhitespace()
    {
        NotesService.Append("   padded   ");

        var content = File.ReadAllText(NotesService.TodayPath);
        content.Should().Contain("â€” padded");
        content.Should().NotContain("    padded   "); // leading-whitespace gone
    }

    [Theory]
    [InlineData("")]
    [InlineData("   ")]
    [InlineData("\t\n")]
    public void Append_RejectsEmptyOrWhitespaceText(string text)
    {
        var ok = NotesService.Append(text);

        ok.Should().BeFalse();
        File.Exists(NotesService.TodayPath).Should().BeFalse(
            "an empty append shouldn't create the daily file");
    }

    [Fact]
    public void TodayPath_ReflectsCurrentDate_AndOverride()
    {
        var path = NotesService.TodayPath;

        Path.GetDirectoryName(path).Should().Be(_tempDir);
        Path.GetFileName(path).Should().MatchRegex(@"\d{4}-\d{2}-\d{2}\.md");
    }
}
