using Microsoft.Playwright;

namespace Books.E2E.Tests.Pages.Modals;

/// <summary>
/// Page object for the Convert Order to Invoice modal.
/// </summary>
public class ConvertToInvoiceModalPage : BasePage
{
    private readonly ILocator _modal;
    private readonly ILocator _infoAlert;
    private readonly ILocator _linesList;
    private readonly ILocator _submitButton;
    private readonly ILocator _cancelButton;

    public ConvertToInvoiceModalPage(IPage page) : base(page)
    {
        _modal = page.Locator(".ant-modal:has-text('Opret faktura fra ordre')");
        _infoAlert = _modal.Locator(".ant-alert-info");
        _linesList = _modal.Locator(".ant-list");
        _submitButton = _modal.GetByRole(AriaRole.Button, new() { Name = "Opret faktura" });
        _cancelButton = _modal.GetByRole(AriaRole.Button, new() { Name = "Annuller" });
    }

    /// <summary>
    /// Waits for the modal to be visible.
    /// </summary>
    public async Task WaitForModalToOpen()
    {
        await _modal.WaitForAsync(new() { State = WaitForSelectorState.Visible, Timeout = 5000 });
    }

    /// <summary>
    /// Checks if the info alert is visible.
    /// </summary>
    public async Task<bool> IsInfoAlertVisible()
    {
        return await _infoAlert.IsVisibleAsync();
    }

    /// <summary>
    /// Gets the number of available lines to invoice.
    /// </summary>
    public async Task<int> GetAvailableLineCount()
    {
        return await _linesList.Locator(".ant-list-item").CountAsync();
    }

    /// <summary>
    /// Selects a line by its description text.
    /// </summary>
    public async Task SelectLine(string description)
    {
        var line = _linesList.Locator($".ant-list-item:has-text('{description}')");
        var checkbox = line.Locator(".ant-checkbox-input");
        if (!await checkbox.IsCheckedAsync())
        {
            await checkbox.ClickAsync();
        }
    }

    /// <summary>
    /// Deselects a line by its description text.
    /// </summary>
    public async Task DeselectLine(string description)
    {
        var line = _linesList.Locator($".ant-list-item:has-text('{description}')");
        var checkbox = line.Locator(".ant-checkbox-input");
        if (await checkbox.IsCheckedAsync())
        {
            await checkbox.ClickAsync();
        }
    }

    /// <summary>
    /// Selects all available lines.
    /// </summary>
    public async Task SelectAllLines()
    {
        var checkboxes = _linesList.Locator(".ant-checkbox-input");
        var count = await checkboxes.CountAsync();
        for (var i = 0; i < count; i++)
        {
            var checkbox = checkboxes.Nth(i);
            if (!await checkbox.IsCheckedAsync())
            {
                await checkbox.ClickAsync();
            }
        }
    }

    /// <summary>
    /// Deselects all lines.
    /// </summary>
    public async Task DeselectAllLines()
    {
        var checkboxes = _linesList.Locator(".ant-checkbox-input");
        var count = await checkboxes.CountAsync();
        for (var i = 0; i < count; i++)
        {
            var checkbox = checkboxes.Nth(i);
            if (await checkbox.IsCheckedAsync())
            {
                await checkbox.ClickAsync();
            }
        }
    }

    /// <summary>
    /// Gets the count of selected lines.
    /// </summary>
    public async Task<int> GetSelectedLineCount()
    {
        var checkboxes = _linesList.Locator(".ant-checkbox-input");
        var count = await checkboxes.CountAsync();
        var selectedCount = 0;
        for (var i = 0; i < count; i++)
        {
            if (await checkboxes.Nth(i).IsCheckedAsync())
            {
                selectedCount++;
            }
        }
        return selectedCount;
    }

    /// <summary>
    /// Checks if a specific line is selected.
    /// </summary>
    public async Task<bool> IsLineSelected(string description)
    {
        var line = _linesList.Locator($".ant-list-item:has-text('{description}')");
        var checkbox = line.Locator(".ant-checkbox-input");
        return await checkbox.IsCheckedAsync();
    }

    /// <summary>
    /// Submits the form to create the invoice.
    /// </summary>
    public async Task Submit()
    {
        await _submitButton.ClickAsync();
        // Wait for modal to close or show error/warning
        await Task.WhenAny(
            _modal.WaitForAsync(new() { State = WaitForSelectorState.Hidden, Timeout = 15000 }),
            Page.Locator(".ant-message-warning, .ant-message-error").WaitForAsync(new() { Timeout = 15000 })
        );
    }

    /// <summary>
    /// Cancels and closes the modal.
    /// </summary>
    public async Task Cancel()
    {
        await _cancelButton.ClickAsync();
        await _modal.WaitForAsync(new() { State = WaitForSelectorState.Hidden, Timeout = 5000 });
    }

    /// <summary>
    /// Checks if the modal is visible.
    /// </summary>
    public async Task<bool> IsVisible()
    {
        return await _modal.IsVisibleAsync();
    }
}
