using ZB.MOM.WW.ScadaBridge.Commons.Types;

namespace ZB.MOM.WW.ScadaBridge.Commons.Tests;

public class NativeAlarmSourceOverrideCsvParserTests
{
    [Fact]
    public void Parse_SimpleFile_ReturnsRowsNoErrors()
    {
        const string csv =
            "SourceName,Connection,SourceReference,Filter\n" +
            "Pressure,ConnA,ns=2;s=Pump.Alarm,Active\n" +
            "Module.Temp,ConnB,ns=2;s=Temp,\n";

        var result = NativeAlarmSourceOverrideCsvParser.Parse(csv);

        Assert.Empty(result.Errors);
        Assert.Equal(2, result.Rows.Count);

        Assert.Equal("Pressure", result.Rows[0].SourceName);
        Assert.Equal("ConnA", result.Rows[0].Connection);
        Assert.Equal("ns=2;s=Pump.Alarm", result.Rows[0].SourceReference);
        Assert.Equal("Active", result.Rows[0].Filter);
        Assert.Equal(2, result.Rows[0].LineNumber);

        Assert.Equal("Module.Temp", result.Rows[1].SourceName);
        Assert.Equal("ConnB", result.Rows[1].Connection);
        Assert.Equal("ns=2;s=Temp", result.Rows[1].SourceReference);
        Assert.Null(result.Rows[1].Filter);
        Assert.Equal(3, result.Rows[1].LineNumber);
    }

    [Fact]
    public void Parse_BlankOverrideFields_BecomeNullInherited()
    {
        const string csv =
            "SourceName,Connection,SourceReference,Filter\n" +
            "Pressure,,,\n";

        var result = NativeAlarmSourceOverrideCsvParser.Parse(csv);

        Assert.Empty(result.Errors);
        var row = Assert.Single(result.Rows);
        Assert.Equal("Pressure", row.SourceName);
        Assert.Null(row.Connection);
        Assert.Null(row.SourceReference);
        Assert.Null(row.Filter);
    }

    [Fact]
    public void Parse_HeaderCaseInsensitive_Accepted()
    {
        const string csv =
            "sourcename,CONNECTION,SourceReference,filter\n" +
            "Pressure,ConnA,ref,\n";

        var result = NativeAlarmSourceOverrideCsvParser.Parse(csv);

        Assert.Empty(result.Errors);
        Assert.Single(result.Rows);
    }

    [Fact]
    public void Parse_QuotedFieldWithComma_PreservesEmbeddedComma()
    {
        const string csv =
            "SourceName,Connection,SourceReference,Filter\n" +
            "Pressure,ConnA,\"ns=2;s=a,b,c\",Active\n";

        var result = NativeAlarmSourceOverrideCsvParser.Parse(csv);

        Assert.Empty(result.Errors);
        var row = Assert.Single(result.Rows);
        Assert.Equal("ns=2;s=a,b,c", row.SourceReference);
    }

    [Fact]
    public void Parse_MissingHeader_ReturnsHeaderError()
    {
        const string csv = "Pressure,ConnA,ref,Active\n";

        var result = NativeAlarmSourceOverrideCsvParser.Parse(csv);

        Assert.Empty(result.Rows);
        var error = Assert.Single(result.Errors);
        Assert.Contains("SourceName,Connection,SourceReference,Filter", error);
    }

    [Fact]
    public void Parse_WrongColumnCount_ReportsPerLineErrorAndSkipsRow()
    {
        const string csv =
            "SourceName,Connection,SourceReference,Filter\n" +
            "Pressure,ConnA\n" +
            "Temp,ConnB,ref,Active\n";

        var result = NativeAlarmSourceOverrideCsvParser.Parse(csv);

        var error = Assert.Single(result.Errors);
        Assert.Contains("Line 2", error);
        Assert.Contains("expected 4 columns", error);
        // Valid rows still flow through.
        var row = Assert.Single(result.Rows);
        Assert.Equal("Temp", row.SourceName);
    }

    [Fact]
    public void Parse_BlankSourceName_ReportsError()
    {
        const string csv =
            "SourceName,Connection,SourceReference,Filter\n" +
            ",ConnA,ref,Active\n";

        var result = NativeAlarmSourceOverrideCsvParser.Parse(csv);

        Assert.Empty(result.Rows);
        var error = Assert.Single(result.Errors);
        Assert.Contains("SourceName must not be blank", error);
    }

    [Fact]
    public void Parse_UnterminatedQuote_ReportsError()
    {
        const string csv =
            "SourceName,Connection,SourceReference,Filter\n" +
            "Pressure,ConnA,\"ns=2;s=open,Active\n";

        var result = NativeAlarmSourceOverrideCsvParser.Parse(csv);

        Assert.Empty(result.Rows);
        Assert.Contains(result.Errors, e => e.Contains("Unterminated quoted field"));
    }

    [Fact]
    public void Parse_BlankLinesSkippedWithoutError()
    {
        const string csv =
            "SourceName,Connection,SourceReference,Filter\n" +
            "\n" +
            "Pressure,ConnA,ref,Active\n" +
            "   \n";

        var result = NativeAlarmSourceOverrideCsvParser.Parse(csv);

        Assert.Empty(result.Errors);
        Assert.Single(result.Rows);
    }
}
