using Jiaowu.Api.Infrastructure.Configuration;

namespace Jiaowu.Api.Tests;

public sealed class EnvironmentFileTests
{
    [Fact]
    public async Task Load_reads_env_file_without_overwriting_process_environment()
    {
        var suffix = Guid.NewGuid().ToString("N");
        var existingKey = $"JIAOWU_TEST_EXISTING_{suffix}";
        var fileKey = $"JIAOWU_TEST_FILE_{suffix}";
        var pathKey = $"JIAOWU_TEST_PATH_{suffix}";
        var directory = CreateTemporaryDirectory();
        var path = Path.Combine(directory, ".env");
        await File.WriteAllLinesAsync(
            path,
            [
                "# comment",
                $"export {existingKey}=from-file",
                $"{fileKey}=first",
                $"{fileKey}='value;with#characters'",
                $"{pathKey}=\"C:\\certs\\mysql-ca.pem\""
            ]);
        Environment.SetEnvironmentVariable(existingKey, "from-process");

        try
        {
            var loadedPath = EnvironmentFile.Load(path);

            Assert.Equal(Path.GetFullPath(path), loadedPath);
            Assert.Equal(
                "from-process",
                Environment.GetEnvironmentVariable(existingKey));
            Assert.Equal(
                "value;with#characters",
                Environment.GetEnvironmentVariable(fileKey));
            Assert.Equal(
                @"C:\certs\mysql-ca.pem",
                Environment.GetEnvironmentVariable(pathKey));
        }
        finally
        {
            Environment.SetEnvironmentVariable(existingKey, null);
            Environment.SetEnvironmentVariable(fileKey, null);
            Environment.SetEnvironmentVariable(pathKey, null);
            Directory.Delete(directory, recursive: true);
        }
    }

    [Fact]
    public void Load_rejects_an_explicit_missing_file()
    {
        var path = Path.Combine(
            Path.GetTempPath(),
            $"jiaowu-missing-{Guid.NewGuid():N}",
            ".env");

        var exception = Assert.Throws<FileNotFoundException>(
            () => EnvironmentFile.Load(path));

        Assert.Equal(Path.GetFullPath(path), exception.FileName);
    }

    [Fact]
    public async Task Load_reports_the_line_number_for_malformed_values()
    {
        var directory = CreateTemporaryDirectory();
        var path = Path.Combine(directory, ".env");
        await File.WriteAllLinesAsync(
            path,
            [
                "# comment",
                "Jwt__Key=\"not-closed"
            ]);

        try
        {
            var exception = Assert.Throws<FormatException>(
                () => EnvironmentFile.Load(path));

            Assert.Contains("第 2 行", exception.Message);
            Assert.Contains("没有正确闭合", exception.Message);
        }
        finally
        {
            Directory.Delete(directory, recursive: true);
        }
    }

    private static string CreateTemporaryDirectory()
    {
        var path = Path.Combine(
            Path.GetTempPath(),
            "jiaowu-env-tests",
            Guid.NewGuid().ToString("N"));
        Directory.CreateDirectory(path);
        return path;
    }
}
