using System.Text.Json;
using Google.Protobuf;
using ZB.MOM.WW.MxGateway.Client;
using ZB.MOM.WW.MxGateway.Contracts.Proto;

namespace ZB.MOM.WW.MxGateway.Client.Tests;

public sealed class MxStatusProxyExtensionsTests
{
    /// <summary>Verifies that fixture statuses correctly project success and preserve raw integer fields.</summary>
    [Fact]
    public void FixtureStatuses_ProjectSuccessAndPreserveRawFields()
    {
        using JsonDocument document = JsonDocument.Parse(ReadFixture(
            "statuses",
            "status-conversion-cases.json"));

        foreach (JsonElement testCase in document.RootElement.GetProperty("cases").EnumerateArray())
        {
            MxStatusProxy status = JsonParser.Default.Parse<MxStatusProxy>(
                testCase.GetProperty("status").GetRawText());

            bool wantSuccess = testCase.GetProperty("wantSuccess").GetBoolean();
            Assert.Equal(wantSuccess, status.IsSuccess());
            Assert.Equal(
                testCase.GetProperty("status").GetProperty("rawCategory").GetInt32(),
                status.RawCategory);
            Assert.Equal(
                testCase.GetProperty("status").GetProperty("rawDetectedBy").GetInt32(),
                status.RawDetectedBy);
        }
    }

    /// <summary>Verifies that the raw success member never overrides the authoritative category.</summary>
    [Theory]
    [InlineData(MxStatusCategory.Ok, 0, true)]
    [InlineData(MxStatusCategory.Ok, 1, true)]
    [InlineData(MxStatusCategory.CommunicationError, 1, false)]
    [InlineData(MxStatusCategory.Unspecified, 1, false)]
    public void IsSuccess_BranchesOnCategoryOnly(
        MxStatusCategory category,
        int success,
        bool expected)
    {
        MxStatusProxy status = new() { Category = category, Success = success };

        Assert.Equal(expected, status.IsSuccess());
    }

    private static string ReadFixture(string category, string fileName)
    {
        DirectoryInfo directory = new(AppContext.BaseDirectory);
        while (directory is not null)
        {
            string path = Path.Combine(
                directory.FullName,
                "clients",
                "proto",
                "fixtures",
                "behavior",
                category,
                fileName);

            if (File.Exists(path))
            {
                return File.ReadAllText(path);
            }

            directory = directory.Parent!;
        }

        throw new FileNotFoundException(fileName);
    }
}
