import asyncio
from random import randint

import pytest

URL = "https://lapalabradeldia.com/"

JUGAR_BUTTON_TEXT = "¡Jugar!"
CARD1_CSS = "#board .react-card-flip:nth-of-type(1)"
CARD2_CSS = "#board .react-card-flip:nth-of-type(2)"
CARD3_CSS = "#board .react-card-flip:nth-of-type(3)"
CARD4_CSS = "#board .react-card-flip:nth-of-type(4)"
CARD5_CSS = "#board .react-card-flip:nth-of-type(5)"
LETTERS_CSS = "#keyboard button:not(:has(svg))"  # avoid check and delete buttons


async def letters_sometimes_vanish(client):
    await client.navigate(URL, wait="load")
    client.await_text(JUGAR_BUTTON_TEXT, is_displayed=True).click()
    letters = client.await_css(LETTERS_CSS, is_displayed=True, all=True)
    body = client.find_css("body")

    # This is a very subtle test, because the problem isn't well-understood. I found that I could
    # only reproduce the issue if I move the mouse immediately after clicking a letter, while the
    # css animation runs. Then the card will sometimes vanish immediately after the animation ends,
    # and if I move the mouse again, it seems to reappear. So this test will simulate that kind of
    # movement while clicking on 5 random letters, then wait a half-second, see if any of the cards
    # are invisible (by taking a "screenshot" of the element, with their CSS borders hidden to make
    # is_one_solid_color not have to fuzz), and try another 5 random letters a few times just to make
    # sure the cards always appear. The need for delaying the various simulated events during the
    # animation makes this test slower than it probably needs to be, but that's fine.
    client.add_stylesheet(
        "#board .react-card-flip * { border:0 !important; animation-duration:0.5s !important; }"
    )

    # click on 5 random letters, check if any are invisible, then delete them and retry
    # repeat this 10 times, and presume everything is fine if none disappear.
    for attempt in range(10):
        for click_five_keys in range(5):
            letter = letters[randint(0, len(letters) - 1)]

            coords = client.get_element_screen_position(letter)
            coords = [coords[0] + 20, coords[1] + 20]
            await client.apz_down(coords=coords)
            await asyncio.sleep(0.025)
            coords = [coords[0] + 20, coords[1] + 20]
            await client.send_apz_mouse_event("move", coords=coords)
            await client.apz_up(coords=coords)

            await asyncio.sleep(0.025)
            await client.send_apz_mouse_event(
                "move", coords=[coords[0] + 50, coords[1] + 50]
            )
            await asyncio.sleep(0.025)
            await client.send_apz_mouse_event(
                "move", coords=[coords[0] + 100, coords[1] + 100]
            )
            await asyncio.sleep(0.025)
            await client.send_apz_mouse_event(
                "move", coords=[coords[0] + 150, coords[1] + 150]
            )
            await asyncio.sleep(0.025)
            await client.send_apz_mouse_event(
                "move", coords=[coords[0] + 200, coords[1] + 200]
            )
            await asyncio.sleep(0.025)

        # wait a moment to let the animations settle down to increase the
        # likelihood that we'll see the problem.
        await asyncio.sleep(0.5)

        if (
            client.is_one_solid_color(client.find_css(CARD1_CSS))
            or client.is_one_solid_color(client.find_css(CARD2_CSS))
            or client.is_one_solid_color(client.find_css(CARD3_CSS))
            or client.is_one_solid_color(client.find_css(CARD4_CSS))
            or client.is_one_solid_color(client.find_css(CARD5_CSS))
        ):
            return True

        # press backspace key 5 times to clear the inputs so we can try again
        for backspace in range(5):
            body.send_keys("\ue003")

    return False


@pytest.mark.skip_platforms("android")
@pytest.mark.asyncio
@pytest.mark.with_interventions
async def test_enabled(client):
    assert not await letters_sometimes_vanish(client)


@pytest.mark.skip_platforms("android")
@pytest.mark.asyncio
@pytest.mark.without_interventions
async def test_disabled(client):
    assert await letters_sometimes_vanish(client)
