import re
from typing import cast
from urllib.parse import urlencode

from notifications_python_client import NotificationsAPIClient
from playwright.sync_api import Locator, Page, expect

from tests.e2e.config import EndToEndTestSecrets


def get_context_aware_textbox_locator_by_name(page: Page, name: str) -> Locator:
    return page.locator(
        ".app-context-aware-editor__editor-container",
        has=page.get_by_role("textbox", name=name),
    ).get_by_role("textbox", name=name)


def wait_for_context_aware_textarea_to_be_ready(page: Page, textarea_id: str) -> None:
    expect(page.locator(f".app-context-aware-editor__visible-textarea[id='{textarea_id}']")).to_be_attached()


def extract_email_link(email: dict[str, str]) -> str:
    pattern = r"https?:\/\/[\w-]+(?:\.[\w]+)+(?:[\w.,@?^=%&:\/~+#-]*[\w@?^=%&\/~+#-])?"

    return cast(str, re.findall(pattern, email["body"])[0])


def retrieve_magic_link(notification_id: str, e2e_test_secrets: EndToEndTestSecrets) -> str:
    client = NotificationsAPIClient(e2e_test_secrets.GOVUK_NOTIFY_API_KEY)
    email = client.get_notification_by_id(notification_id)

    if not email:
        raise LookupError("Could not find a corresponding find magic link in GOV.UK Notify")

    return extract_email_link(email)


def delete_grant_recipient_through_admin(
    page: Page, domain: str, search: str, expected_grant_recipients_matching_search: int = 1
) -> None:
    query = urlencode(query=dict(search=search))
    page.goto(f"{domain}/deliver/admin/grantrecipient/?{query}")

    grant_recipients = page.get_by_role("link", name=re.compile(search)).all()
    assert len(grant_recipients) == expected_grant_recipients_matching_search
    page.check("#select-all")
    page.locator("button:has-text('Actions')").click()
    page.locator(f"button:has-text('Delete ({expected_grant_recipients_matching_search} selected)')").click()
    page.locator("button:has-text('Confirm delete')").click()


def delete_grant_through_admin(page: Page, domain: str, search: str) -> None:
    query = urlencode(query=dict(search=search))
    page.goto(f"{domain}/deliver/admin/grant/?{query}")

    assert len(page.get_by_role("link", name=re.compile(search)).all()) == 1

    page.check("#select-all")
    page.locator("button:has-text('Delete (1 selected)')").click()
    page.locator("button:has-text('Confirm delete')").click()
