using Microsoft.Playwright;

namespace Books.E2E.Tests.Pages;

/// <summary>
/// Base class for all page objects with common utilities.
/// </summary>
public abstract class BasePage
{
    protected readonly IPage Page;

    protected BasePage(IPage page)
    {
        Page = page;
    }

    protected ILocator Locator(string selector) => Page.Locator(selector);

    /// <summary>
    /// Waits for network activity to settle.
    /// </summary>
    protected async Task WaitForNetworkIdleAsync()
    {
        await Page.WaitForLoadStateAsync(LoadState.NetworkIdle);
    }

    /// <summary>
    /// Clicks a button by its visible text.
    /// </summary>
    protected async Task ClickButtonAsync(string text)
    {
        await Page.GetByRole(AriaRole.Button, new() { Name = text }).ClickAsync();
    }

    /// <summary>
    /// Fills an input field by its label.
    /// </summary>
    protected async Task FillInputAsync(string label, string value)
    {
        await Page.GetByLabel(label).FillAsync(value);
    }

    /// <summary>
    /// Selects an option in an Ant Design Select component by label.
    /// </summary>
    protected async Task SelectAntOptionAsync(string formItemLabel, string optionText)
    {
        // Find the form item containing the label
        var formItem = Page.Locator($".ant-form-item:has(.ant-form-item-label:has-text('{formItemLabel}'))");

        // Click the select to open dropdown
        var select = formItem.Locator(".ant-select");
        await select.ClickAsync();

        // Wait for dropdown and click option
        var dropdown = Page.Locator(".ant-select-dropdown:visible");
        await dropdown.WaitForAsync();

        var option = dropdown.Locator($".ant-select-item-option:has-text('{optionText}')");
        await option.ClickAsync();

        // Wait for dropdown to close
        await Task.Delay(100);
    }

    /// <summary>
    /// Waits for an element to be visible.
    /// </summary>
    protected async Task WaitForVisibleAsync(string selector, int timeoutMs = 5000)
    {
        await Page.Locator(selector).WaitForAsync(new() { Timeout = timeoutMs });
    }

    /// <summary>
    /// Checks if an element is visible.
    /// </summary>
    protected async Task<bool> IsVisibleAsync(string selector)
    {
        return await Page.Locator(selector).IsVisibleAsync();
    }
}
