using Books.E2E.Tests.Infrastructure;
using Books.E2E.Tests.Pages;
using Books.E2E.Tests.Pages.Modals;
using Books.E2E.Tests.TestData;

namespace Books.E2E.Tests.Tests.Orders;

/// <summary>
/// E2E tests for order workflow: confirm, cancel, convert to invoice.
/// Tests the complete order lifecycle.
///
/// Prerequisites:
/// - Backend and frontend running
/// - At least one company and customer exist
/// </summary>
[Trait("Category", "E2E")]
public class OrderWorkflowTests : E2ETestBase
{
    public OrderWorkflowTests(
        E2ETestFixture fixture,
        PlaywrightFixture playwright)
        : base(fixture, playwright)
    {
    }

    [Fact]
    public async Task ConfirmOrder_WithLines_ChangesStatusToConfirmed()
    {
        // Arrange - Create order with a line
        await Page.GotoAsync($"{Config.FrontendUrl}/ordrer");
        var ordersPage = new OrdersPage(Page);
        await ordersPage.WaitForPageToLoad();

        await ordersPage.ClickNewOrder();
        var createModal = new CreateOrderModalPage(Page);
        await createModal.WaitForModalToOpen();
        await createModal.SelectCustomer("");
        await createModal.Submit();

        var drawer = new OrderDrawerPage(Page);
        await drawer.WaitForDrawerToOpen();

        // Add a line (required for confirmation)
        await drawer.ClickAddLine();
        var addLineModal = new AddOrderLineModalPage(Page);
        await addLineModal.WaitForModalToOpen();
        await addLineModal.FillBasicLine("Test produkt til bekraeftelse", 2, 750m);
        await addLineModal.Submit();
        await Task.Delay(500);

        // Act - Confirm the order
        await drawer.ClickConfirm();
        await Task.Delay(1000); // Wait for confirmation to process

        // Assert
        var status = await drawer.GetOrderStatus();
        status.Should().Contain("Bekraeftet", "Order status should change to confirmed");

        // Confirm button should no longer be visible
        (await drawer.IsConfirmButtonVisible()).Should().BeFalse("Confirm button should be hidden after confirmation");

        // Create Invoice button should now be visible
        (await drawer.IsCreateInvoiceButtonVisible()).Should().BeTrue("Create Invoice button should be visible for confirmed orders");
    }

    [Fact]
    public async Task ConfirmOrder_WithoutLines_ShowsWarning()
    {
        // Arrange - Create order without lines
        await Page.GotoAsync($"{Config.FrontendUrl}/ordrer");
        var ordersPage = new OrdersPage(Page);
        await ordersPage.WaitForPageToLoad();

        await ordersPage.ClickNewOrder();
        var createModal = new CreateOrderModalPage(Page);
        await createModal.WaitForModalToOpen();
        await createModal.SelectCustomer("");
        await createModal.Submit();

        var drawer = new OrderDrawerPage(Page);
        await drawer.WaitForDrawerToOpen();

        // Verify confirm button is disabled (no lines)
        var confirmButton = Page.Locator(".ant-drawer").GetByRole(AriaRole.Button, new() { Name = "Bekraeft" });
        var isDisabled = await confirmButton.IsDisabledAsync();

        // Assert
        isDisabled.Should().BeTrue("Confirm button should be disabled when order has no lines");
    }

    [Fact]
    public async Task CancelOrder_FromDraft_CancelsSuccessfully()
    {
        // Arrange - Create a draft order
        await Page.GotoAsync($"{Config.FrontendUrl}/ordrer");
        var ordersPage = new OrdersPage(Page);
        await ordersPage.WaitForPageToLoad();

        await ordersPage.ClickNewOrder();
        var createModal = new CreateOrderModalPage(Page);
        await createModal.WaitForModalToOpen();
        await createModal.SelectCustomer("");
        await createModal.Submit();

        var drawer = new OrderDrawerPage(Page);
        await drawer.WaitForDrawerToOpen();

        // Act - Cancel the order
        await drawer.ClickCancel();

        var cancelModal = new CancelOrderModalPage(Page);
        await cancelModal.WaitForModalToOpen();

        // Verify warning is shown
        (await cancelModal.IsWarningAlertVisible()).Should().BeTrue("Warning about cancellation should be visible");

        // Enter reason and submit
        await cancelModal.EnterReason("E2E Test - automatisk annullering");
        await cancelModal.Submit();

        await Task.Delay(1000); // Wait for cancellation to process

        // Assert
        var status = await drawer.GetOrderStatus();
        status.Should().Contain("Annulleret", "Order status should be cancelled");

        // Cancel button should no longer be visible
        (await drawer.IsCancelButtonVisible()).Should().BeFalse("Cancel button should be hidden after cancellation");
    }

    [Fact]
    public async Task CancelOrder_WithoutReason_ShowsValidationError()
    {
        // Arrange
        await Page.GotoAsync($"{Config.FrontendUrl}/ordrer");
        var ordersPage = new OrdersPage(Page);
        await ordersPage.WaitForPageToLoad();

        await ordersPage.ClickNewOrder();
        var createModal = new CreateOrderModalPage(Page);
        await createModal.WaitForModalToOpen();
        await createModal.SelectCustomer("");
        await createModal.Submit();

        var drawer = new OrderDrawerPage(Page);
        await drawer.WaitForDrawerToOpen();

        // Act - Try to cancel without reason
        await drawer.ClickCancel();

        var cancelModal = new CancelOrderModalPage(Page);
        await cancelModal.WaitForModalToOpen();
        await cancelModal.Submit(); // Don't enter reason

        // Assert
        (await cancelModal.HasValidationErrors()).Should().BeTrue("Should show validation error for missing reason");
    }

    [Fact]
    public async Task ConvertToInvoice_FullOrder_CreatesInvoice()
    {
        // Arrange - Create and confirm order
        await Page.GotoAsync($"{Config.FrontendUrl}/ordrer");
        var ordersPage = new OrdersPage(Page);
        await ordersPage.WaitForPageToLoad();

        await ordersPage.ClickNewOrder();
        var createModal = new CreateOrderModalPage(Page);
        await createModal.WaitForModalToOpen();
        await createModal.SelectCustomer("");
        await createModal.Submit();

        var drawer = new OrderDrawerPage(Page);
        await drawer.WaitForDrawerToOpen();

        // Add lines
        await drawer.ClickAddLine();
        var addLineModal = new AddOrderLineModalPage(Page);
        await addLineModal.WaitForModalToOpen();
        await addLineModal.FillBasicLine("Produkt A", 2, 1000m);
        await addLineModal.Submit();
        await Task.Delay(500);

        await drawer.ClickAddLine();
        addLineModal = new AddOrderLineModalPage(Page);
        await addLineModal.WaitForModalToOpen();
        await addLineModal.FillBasicLine("Produkt B", 1, 500m);
        await addLineModal.Submit();
        await Task.Delay(500);

        // Confirm order
        await drawer.ClickConfirm();
        await Task.Delay(1000);

        // Act - Convert to invoice
        await drawer.ClickCreateInvoice();

        var convertModal = new ConvertToInvoiceModalPage(Page);
        await convertModal.WaitForModalToOpen();

        // Verify all lines are available
        var availableLines = await convertModal.GetAvailableLineCount();
        availableLines.Should().Be(2, "Both lines should be available for invoicing");

        // Select all lines (should be pre-selected)
        await convertModal.SelectAllLines();
        await convertModal.Submit();

        // Assert - Success message should appear
        var successMessage = Page.Locator(".ant-message-success");
        await successMessage.WaitForAsync(new() { Timeout = 10000 });
        (await successMessage.IsVisibleAsync()).Should().BeTrue("Success message should appear after invoice creation");
    }

    [Fact]
    public async Task ConvertToInvoice_PartialOrder_CreatesPartialInvoice()
    {
        // Arrange - Create and confirm order with multiple lines
        await Page.GotoAsync($"{Config.FrontendUrl}/ordrer");
        var ordersPage = new OrdersPage(Page);
        await ordersPage.WaitForPageToLoad();

        await ordersPage.ClickNewOrder();
        var createModal = new CreateOrderModalPage(Page);
        await createModal.WaitForModalToOpen();
        await createModal.SelectCustomer("");
        await createModal.Submit();

        var drawer = new OrderDrawerPage(Page);
        await drawer.WaitForDrawerToOpen();

        // Add multiple lines
        var lines = new[] { "Fase 1 - Analyse", "Fase 2 - Design", "Fase 3 - Implementering" };
        foreach (var line in lines)
        {
            await drawer.ClickAddLine();
            var addLineModal = new AddOrderLineModalPage(Page);
            await addLineModal.WaitForModalToOpen();
            await addLineModal.FillBasicLine(line, 1, 5000m);
            await addLineModal.Submit();
            await Task.Delay(300);
        }

        // Confirm order
        await drawer.ClickConfirm();
        await Task.Delay(1000);

        // Act - Convert only first line to invoice
        await drawer.ClickCreateInvoice();

        var convertModal = new ConvertToInvoiceModalPage(Page);
        await convertModal.WaitForModalToOpen();

        // Deselect all, then select only first line
        await convertModal.DeselectAllLines();
        await convertModal.SelectLine("Fase 1");

        var selectedCount = await convertModal.GetSelectedLineCount();
        selectedCount.Should().Be(1, "Only one line should be selected");

        await convertModal.Submit();

        // Assert
        var successMessage = Page.Locator(".ant-message-success");
        await successMessage.WaitForAsync(new() { Timeout = 10000 });

        // Refresh drawer to see updated state
        await Task.Delay(1000);

        // Order should still have uninvoiced lines
        (await drawer.IsCreateInvoiceButtonVisible()).Should().BeTrue("Create Invoice button should still be visible for partial invoicing");
    }

    [Fact]
    public async Task ConvertToInvoice_NoLinesSelected_ShowsWarning()
    {
        // Arrange - Create and confirm order
        await Page.GotoAsync($"{Config.FrontendUrl}/ordrer");
        var ordersPage = new OrdersPage(Page);
        await ordersPage.WaitForPageToLoad();

        await ordersPage.ClickNewOrder();
        var createModal = new CreateOrderModalPage(Page);
        await createModal.WaitForModalToOpen();
        await createModal.SelectCustomer("");
        await createModal.Submit();

        var drawer = new OrderDrawerPage(Page);
        await drawer.WaitForDrawerToOpen();

        await drawer.ClickAddLine();
        var addLineModal = new AddOrderLineModalPage(Page);
        await addLineModal.WaitForModalToOpen();
        await addLineModal.FillBasicLine("Test produkt", 1, 1000m);
        await addLineModal.Submit();
        await Task.Delay(500);

        await drawer.ClickConfirm();
        await Task.Delay(1000);

        // Act - Try to convert with no lines selected
        await drawer.ClickCreateInvoice();

        var convertModal = new ConvertToInvoiceModalPage(Page);
        await convertModal.WaitForModalToOpen();

        await convertModal.DeselectAllLines();
        await convertModal.Submit();

        // Assert - Warning should appear
        var warningMessage = Page.Locator(".ant-message-warning");
        await warningMessage.WaitForAsync(new() { Timeout = 5000 });
        (await warningMessage.IsVisibleAsync()).Should().BeTrue("Warning should appear when no lines selected");
    }
}
