using System.Diagnostics;
using System.Runtime.CompilerServices;
using Sbroenne.ExcelMcp.ComInterop.Session;
using Sbroenne.ExcelMcp.Core.Commands.Table;
using Sbroenne.ExcelMcp.Core.Models;
using Xunit;

namespace Sbroenne.ExcelMcp.Core.Tests.Helpers;

/// <summary>
/// Fixture that creates ONE Table test file per test CLASS.
/// The fixture initialization IS the test for Table creation.
/// - Created ONCE before any tests run (~5-10s)
/// - Shared READ-ONLY by all tests in the class
/// - Each test gets its own batch (isolation at batch level)
/// - No file sharing between test classes
/// - Creation results exposed for validation tests
/// - Provides CreateModificationTestFile() for tests that need isolated files
/// </summary>
public class TableTestsFixture : IAsyncLifetime
{
    private readonly string _tempDir;
    private readonly TableCommands _tableCommands = new TableCommands();

    /// <summary>
    /// Path to the test Table file (shared READ-ONLY)
    /// </summary>
    public string TestFilePath { get; private set; } = null!;

    /// <summary>
    /// Temp directory for modification tests that need unique files
    /// </summary>
    public string TempDir => _tempDir;

    /// <summary>
    /// Results of Table creation (exposed for validation)
    /// </summary>
    public TableCreationResult CreationResult { get; private set; } = null!;
    /// <inheritdoc/>

    public TableTestsFixture()
    {
        _tempDir = Path.Join(Path.GetTempPath(), $"TableTests_{Guid.NewGuid():N}");
        Directory.CreateDirectory(_tempDir);
    }

    /// <summary>
    /// Called ONCE before any tests in the class run.
    /// This IS the test for Table creation - if it fails, all tests fail (correct behavior).
    /// Tests: file creation, data creation, TableCommands.Create(), persistence.
    /// </summary>
    public Task InitializeAsync()
    {
        var sw = Stopwatch.StartNew();

        TestFilePath = Path.Join(_tempDir, "TableTest.xlsx");
        CreationResult = new TableCreationResult();

        try
        {
            // TEST 1: File Creation
            using (var manager = new SessionManager())
            {
                var sessionId = manager.CreateSessionForNewFile(TestFilePath, show: false);
                manager.CloseSession(sessionId, save: true);
            }

            CreationResult.FileCreated = true;

            using var batch = ExcelSession.BeginBatch(TestFilePath);

            // TEST 2: Data Creation and Table Creation

            // Create sample sales data
            batch.Execute((ctx, ct) =>
            {
                dynamic sheet = ctx.Book.Worksheets[1];
                sheet.Name = "Sales";

                // Add headers
                sheet.Range["A1"].Value2 = "Region";
                sheet.Range["B1"].Value2 = "Product";
                sheet.Range["C1"].Value2 = "Amount";
                sheet.Range["D1"].Value2 = "Date";

                // Add sample data
                sheet.Range["A2"].Value2 = "North";
                sheet.Range["B2"].Value2 = "Widget";
                sheet.Range["C2"].Value2 = 100;
                sheet.Range["D2"].Value2 = new DateTime(2025, 1, 15);

                sheet.Range["A3"].Value2 = "South";
                sheet.Range["B3"].Value2 = "Gadget";
                sheet.Range["C3"].Value2 = 250;
                sheet.Range["D3"].Value2 = new DateTime(2025, 2, 20);

                sheet.Range["A4"].Value2 = "East";
                sheet.Range["B4"].Value2 = "Widget";
                sheet.Range["C4"].Value2 = 150;
                sheet.Range["D4"].Value2 = new DateTime(2025, 3, 10);

                sheet.Range["A5"].Value2 = "West";
                sheet.Range["B5"].Value2 = "Gadget";
                sheet.Range["C5"].Value2 = 300;
                sheet.Range["D5"].Value2 = new DateTime(2025, 1, 25);

                return 0;
            });

            // Create Table using TableCommands
            var tableCommands = new TableCommands();
            // Create throws on error, so reaching here means success
            tableCommands.Create(
                batch, "Sales", "SalesTable", "A1:D5", hasHeaders: true, tableStyle: TableStylePresets.Medium2);

            CreationResult.TablesCreated = 1;

            // TEST 3: Persistence (Save)
            batch.Save();

            sw.Stop();
            CreationResult.Success = true;
            CreationResult.CreationTimeSeconds = sw.Elapsed.TotalSeconds;
        }
        catch (Exception ex)
        {
            CreationResult.Success = false;
            CreationResult.ErrorMessage = ex.Message;
            sw.Stop();
            throw; // Fail all tests in class (correct behavior - no point testing if creation failed)
        }

        return Task.CompletedTask;
    }

    /// <summary>
    /// Called ONCE after all tests in the class complete.
    /// </summary>
    public Task DisposeAsync()
    {
        try
        {
            if (Directory.Exists(_tempDir))
            {
                Directory.Delete(_tempDir, recursive: true);
            }
        }
        catch
        {
            // Cleanup is best-effort
        }
        return Task.CompletedTask;
    }

    /// <summary>
    /// Creates a unique test file with SalesTable for modification tests.
    /// Use this for tests that modify the table (delete, rename, resize, etc.)
    /// </summary>
    /// <param name="testName">Auto-populated from caller method name</param>
    /// <returns>Path to the unique test file</returns>
    public string CreateModificationTestFile([CallerMemberName] string testName = "")
    {
        var guid = Guid.NewGuid().ToString("N")[..8];
        var testFile = Path.Join(_tempDir, $"Table_{testName}_{guid}.xlsx");

        using (var manager = new SessionManager())
        {
            var sessionId = manager.CreateSessionForNewFile(testFile, show: false);
            manager.CloseSession(sessionId, save: true);
        }

        using var batch = ExcelSession.BeginBatch(testFile);

        // Create worksheet with sample data
        batch.Execute((ctx, ct) =>
        {
            dynamic sheet = ctx.Book.Worksheets[1];
            sheet.Name = "Sales";

            // Headers
            sheet.Range["A1"].Value2 = "Region";
            sheet.Range["B1"].Value2 = "Product";
            sheet.Range["C1"].Value2 = "Amount";
            sheet.Range["D1"].Value2 = "Date";

            // Sample data
            sheet.Range["A2"].Value2 = "North";
            sheet.Range["B2"].Value2 = "Widget";
            sheet.Range["C2"].Value2 = 100;
            sheet.Range["D2"].Value2 = new DateTime(2025, 1, 15);

            sheet.Range["A3"].Value2 = "South";
            sheet.Range["B3"].Value2 = "Gadget";
            sheet.Range["C3"].Value2 = 250;
            sheet.Range["D3"].Value2 = new DateTime(2025, 2, 20);

            sheet.Range["A4"].Value2 = "East";
            sheet.Range["B4"].Value2 = "Widget";
            sheet.Range["C4"].Value2 = 150;
            sheet.Range["D4"].Value2 = new DateTime(2025, 3, 10);

            sheet.Range["A5"].Value2 = "West";
            sheet.Range["B5"].Value2 = "Gadget";
            sheet.Range["C5"].Value2 = 300;
            sheet.Range["D5"].Value2 = new DateTime(2025, 1, 25);

            return 0;
        });

        // Create table from range A1:D5
        _tableCommands.Create(batch, "Sales", "SalesTable", "A1:D5", true, TableStylePresets.Medium2);

        batch.Save();
        return testFile;
    }
}

/// <summary>
/// Results of Table creation (exposed by fixture for validation tests)
/// </summary>
public class TableCreationResult
{
    /// <inheritdoc/>
    public bool Success { get; set; }
    /// <inheritdoc/>
    public bool FileCreated { get; set; }
    /// <inheritdoc/>
    public int TablesCreated { get; set; }
    /// <inheritdoc/>
    public double CreationTimeSeconds { get; set; }
    /// <inheritdoc/>
    public string? ErrorMessage { get; set; }
}




