using FluentAssertions;

namespace OCES.Resonance.Core.Tests;

/// <summary>
/// AudioMetadataReader 单元测试
/// </summary>
public class AudioMetadataReaderTests
{
    readonly AudioMetadataReader _reader;
    readonly string _testDirectory;

    public AudioMetadataReaderTests()
    {
        this._reader = new AudioMetadataReader();
        this._testDirectory = Path.Combine(Path.GetTempPath(), $"MetadataReaderTest_{Guid.NewGuid()}");
        Directory.CreateDirectory(this._testDirectory);
    }

    [Fact]
    public void ReadMetadata_文件不存在_抛出FileNotFoundException()
    {
        // Arrange
        string nonExistentFile = Path.Combine(this._testDirectory, "non_existent.wav");

        // Act & Assert
        Func<AudioFileMeta> act = () => this._reader.ReadMetadata(nonExistentFile);
        act.Should().Throw<FileNotFoundException>();
    }

    [Fact]
    public void ReadMetadata_空文件_仍然返回元数据()
    {
        // Arrange
        string emptyFile = Path.Combine(this._testDirectory, "empty.wav");
        File.WriteAllText(emptyFile, "");

        // Act
        AudioFileMeta result = this._reader.ReadMetadata(emptyFile);

        // Assert
        result.Should().NotBeNull();
        result.Filename.Should().Be("empty.wav");
        result.Path.Should().Be(Path.GetFullPath(emptyFile));
        result.Md5.Should().NotBeNullOrEmpty();
        result.UniqueId.Should().NotBeNullOrEmpty();
    }

    [Fact]
    public void ReadMetadata_生成唯一ID_每次调用都不同()
    {
        // Arrange
        string testFile = Path.Combine(this._testDirectory, "test.wav");
        File.WriteAllText(testFile, "fake audio content");

        // Act
        AudioFileMeta result1 = this._reader.ReadMetadata(testFile);
        AudioFileMeta result2 = this._reader.ReadMetadata(testFile);

        // Assert
        result1.UniqueId.Should().NotBe(result2.UniqueId);
    }

    [Fact]
    public void ReadMetadata_相同文件_MD5相同()
    {
        // Arrange
        var testFile = Path.Combine(this._testDirectory, "test.wav");
        File.WriteAllText(testFile, "fake audio content");

        // Act
        var result1 = this._reader.ReadMetadata(testFile);
        var result2 = this._reader.ReadMetadata(testFile);

        // Assert
        result1.Md5.Should().Be(result2.Md5);
    }

    [Theory]
    [InlineData(".wav", "WAV")]
    [InlineData(".mp3", "MP3")]
    [InlineData(".flac", "FLAC")]
    [InlineData(".aiff", "AIFF")]
    public void ReadMetadata_不同格式_正确设置Type字段(string extension, string expectedType)
    {
        // Arrange
        string testFile = Path.Combine(this._testDirectory, $"test{extension}");
        File.WriteAllText(testFile, "fake audio content");

        // Act
        AudioFileMeta result = this._reader.ReadMetadata(testFile);

        // Assert
        result.Type.Should().Be(expectedType);
    }

    [Fact]
    public void ReadMetadata_提取文件夹信息()
    {
        // Arrange
        string subDir = Path.Combine(this._testDirectory, "SubFolder");
        Directory.CreateDirectory(subDir);
        string testFile = Path.Combine(subDir, "test.wav");
        File.WriteAllText(testFile, "fake audio content");

        // Act
        AudioFileMeta result = this._reader.ReadMetadata(testFile);

        // Assert
        result.Folder.Should().Be("SubFolder");
        result.Directory.Should().Be(subDir);
    }

    [Fact]
    public void ReadMetadata_设置DateAdded为当前时间()
    {
        // Arrange
        string testFile = Path.Combine(this._testDirectory, "test.wav");
        File.WriteAllText(testFile, "fake audio content");
        DateTime beforeTime = DateTime.Now;

        // Act
        AudioFileMeta result = this._reader.ReadMetadata(testFile);
        DateTime afterTime = DateTime.Now;

        // Assert
        result.DateAdded.Should().BeOnOrAfter(beforeTime);
        result.DateAdded.Should().BeOnOrBefore(afterTime);
    }
}
