using Sbroenne.ExcelMcp.ComInterop.Session;
using Sbroenne.ExcelMcp.Core.Commands.Chart;
using Sbroenne.ExcelMcp.Core.Tests.Helpers;
using Xunit;

namespace Sbroenne.ExcelMcp.Core.Tests.Commands;

/// <summary>
/// Integration tests for Chart data source operations (SetSourceRange, AddSeries, RemoveSeries).
/// </summary>
public partial class ChartCommandsTests
{
    [Fact]
    public void SetSourceRange_RegularChart_UpdatesDataSource()
    {
        // Arrange
        using var batch = ExcelSession.BeginBatch(_fixture.SharedTestFile);

        // Write additional data range for source change test
        batch.Execute((ctx, ct) =>
        {
            dynamic sheet = ctx.Book.Worksheets[1];
            sheet.Range["E1:F5"].Value2 = new object[,] {
                { "New", "Data" },
                { "X", 100 },
                { "Y", 200 },
                { "Z", 300 },
                { "W", 400 }
            };
            return 0;
        });

        var createResult = _commands.CreateFromRange(batch, "Sheet1", "A1:B4", ChartType.ColumnClustered, 50, 50);

        // Act
        _commands.SetSourceRange(batch, createResult.ChartName, "E1:F5");

        // Assert - Verify source range changed (Excel returns SERIES formula with Sheet1 reference)
        var readResult = _commands.Read(batch, createResult.ChartName);
        Assert.Contains("Sheet1", readResult.SourceRange, StringComparison.OrdinalIgnoreCase);
        Assert.Contains("$E$", readResult.SourceRange, StringComparison.OrdinalIgnoreCase);
        Assert.Contains("$F$", readResult.SourceRange, StringComparison.OrdinalIgnoreCase);
    }

    [Fact]
    public void AddSeries_RegularChart_AddsNewSeries()
    {
        // Arrange
        using var batch = ExcelSession.BeginBatch(_fixture.SharedTestFile);

        var createResult = _commands.CreateFromRange(batch, "Sheet1", "A1:B4", ChartType.Line, 50, 50);

        var readBefore = _commands.Read(batch, createResult.ChartName);
        int initialSeriesCount = readBefore.Series.Count;

        // Act
        var addSeriesResult = _commands.AddSeries(
            batch,
            createResult.ChartName,
            "NewSeries",
            "Sheet1!C2:C4",
            "Sheet1!A2:A4");

        // Assert
        Assert.Equal("NewSeries", addSeriesResult.Name);

        // Verify series added
        var readAfter = _commands.Read(batch, createResult.ChartName);
        Assert.Equal(initialSeriesCount + 1, readAfter.Series.Count);
        Assert.Contains(readAfter.Series, s => s.Name == "NewSeries");
    }

    [Fact]
    public void RemoveSeries_RegularChart_RemovesSeries()
    {
        // Arrange
        using var batch = ExcelSession.BeginBatch(_fixture.SharedTestFile);

        var createResult = _commands.CreateFromRange(batch, "Sheet1", "A1:C4", ChartType.ColumnClustered, 50, 50);

        var readBefore = _commands.Read(batch, createResult.ChartName);
        int initialSeriesCount = readBefore.Series.Count;
        Assert.True(initialSeriesCount >= 2, "Need at least 2 series for test");

        // Act - Remove first series (index 1)
        _commands.RemoveSeries(batch, createResult.ChartName, 1);

        // Assert - Verify series removed
        var readAfter = _commands.Read(batch, createResult.ChartName);
        Assert.Equal(initialSeriesCount - 1, readAfter.Series.Count);
    }

    [Fact]
    public void AddSeries_WithoutCategoryRange_CreatesSeriesSuccessfully()
    {
        // Arrange
        using var batch = ExcelSession.BeginBatch(_fixture.SharedTestFile);

        var createResult = _commands.CreateFromRange(batch, "Sheet1", "A1:B4", ChartType.XYScatter, 50, 50);

        // Act - Add series without category range
        var addResult = _commands.AddSeries(batch, createResult.ChartName, "Series3", "Sheet1!C2:C4", null);

        // Assert
        Assert.Equal("Series3", addResult.Name);
    }

    [Fact]
    public void SetSourceRange_NonExistentChart_ReturnsError()
    {
        // Arrange
        using var batch = ExcelSession.BeginBatch(_fixture.SharedTestFile);

        // Act & Assert
        var exception = Assert.Throws<InvalidOperationException>(() =>
            _commands.SetSourceRange(batch, "NonExistent", "A1:B10"));
        Assert.Contains("not found", exception.Message, StringComparison.OrdinalIgnoreCase);
    }

    [Fact]
    public void AddSeries_InvalidSeriesIndex_HandlesGracefully()
    {
        // Arrange
        using var batch = ExcelSession.BeginBatch(_fixture.SharedTestFile);

        var createResult = _commands.CreateFromRange(batch, "Sheet1", "A1:B4", ChartType.Line, 50, 50);

        // Act & Assert - Invalid series index should throw exception
        var exception = Assert.Throws<System.Runtime.InteropServices.COMException>(() =>
            _commands.RemoveSeries(batch, createResult.ChartName, 999));

        Assert.NotNull(exception);
    }

    [Fact]
    public void SetSourceRange_ExpandedRange_UpdatesChartData()
    {
        // Arrange
        using var batch = ExcelSession.BeginBatch(_fixture.SharedTestFile);

        var createResult = _commands.CreateFromRange(batch, "Sheet1", "A1:B3", ChartType.BarClustered, 50, 50);

        // Act - Expand to include more rows
        _commands.SetSourceRange(batch, createResult.ChartName, "A1:B5");

        // Assert - Verify expanded range (Excel returns SERIES formula with Sheet1 reference)
        var readResult = _commands.Read(batch, createResult.ChartName);
        Assert.Contains("Sheet1", readResult.SourceRange, StringComparison.OrdinalIgnoreCase);
        Assert.Contains("$A$", readResult.SourceRange, StringComparison.OrdinalIgnoreCase);
        // Verify it includes row 5 (expanded from 3 to 5)
        Assert.Contains("$5", readResult.SourceRange, StringComparison.OrdinalIgnoreCase);
    }
}




