"""
Tests for the <chives-image> web component.
"""

import json
from pathlib import Path

from playwright.sync_api import expect, Page
import pytest

from chives.media import create_image_entity


@pytest.fixture(autouse=True)
def setup_chives_image_component(page: Page) -> None:
    """
    Intercept the page, open a blank state, and load the chives-image
    component.
    """
    page.goto("about:blank")

    with open("javascript/chives-image.js") as f:
        component_js = f.read()

    page.evaluate(component_js)


def test_render_basic_image(page: Page) -> None:
    """
    The <chives-image> component can render a basic image entity.
    """
    e = create_image_entity(path="tests/fixtures/media/470906.png")
    page.evaluate(
        """
        const elem = document.createElement("chives-image");
        elem.imageEntity = %s;
        document.body.appendChild(elem);
        """
        % json.dumps(e),
    )

    chives_elem = page.locator("chives-image")

    img_elem = chives_elem.locator("img")
    expect(img_elem).to_be_visible()
    assert (img_elem).get_attribute("src") == "tests/fixtures/media/470906.png"
    assert (img_elem).get_attribute("alt") is None


def test_render_thumbnail(page: Page, tmp_path: Path) -> None:
    """
    If you select the `thumbnail` variant, the <chives-image> component
    uses the thumbnail URL.
    """
    e = create_image_entity(
        path="tests/fixtures/media/470906.png",
        thumbnail_config={
            "out_dir": tmp_path,
            "width": 100,
        },
    )
    page.evaluate(
        """
        const elem = document.createElement("chives-image");
        elem.imageEntity = %s;
        elem.variant = 'thumbnail';
        document.body.appendChild(elem);
        """
        % json.dumps(e),
    )

    chives_elem = page.locator("chives-image")

    img_elem = chives_elem.locator("img")
    expect(img_elem).to_be_visible()
    assert (img_elem).get_attribute("src") == e["thumbnail_path"]


def test_skips_thumbnail_if_unavailable(page: Page) -> None:
    """
    If you select the `thumbnail` variant but there's no thumbnail path
    available, the component falls back to the full-sized path.
    """
    e = create_image_entity(path="tests/fixtures/media/470906.png")
    page.evaluate(
        """
        const elem = document.createElement("chives-image");
        elem.imageEntity = %s;
        elem.variant = 'thumbnail';
        document.body.appendChild(elem);
        """
        % json.dumps(e),
    )

    chives_elem = page.locator("chives-image")

    img_elem = chives_elem.locator("img")
    expect(img_elem).to_be_visible()
    assert (img_elem).get_attribute("src") == "tests/fixtures/media/470906.png"


def test_set_thumbnail_path(page: Page) -> None:
    """
    If you set an explicit thumbnailPath, the <chives-image> component
    uses the thumbnail URL.
    """
    e = create_image_entity(path="tests/fixtures/media/470906.png")
    page.evaluate(
        """
        const elem = document.createElement("chives-image");
        elem.imageEntity = %s;
        elem.thumbnailPath = 'https://example.com/thumbnail.png';
        document.body.appendChild(elem);
        """
        % json.dumps(e),
    )

    chives_elem = page.locator("chives-image")

    img_elem = chives_elem.locator("img")
    expect(img_elem).to_be_visible()
    assert (img_elem).get_attribute("src") == "https://example.com/thumbnail.png"


def test_set_href(page: Page) -> None:
    """
    If you set an href, the <chives-image> component links to that URL.
    """
    e = create_image_entity(path="tests/fixtures/media/470906.png")
    page.evaluate(
        """
        const elem = document.createElement("chives-image");
        elem.imageEntity = %s;
        elem.href = 'https://example.com/';
        document.body.appendChild(elem);
        """
        % json.dumps(e),
    )

    chives_elem = page.locator("chives-image")

    a_elem = chives_elem.locator("a")
    expect(a_elem).to_be_visible()
    assert (a_elem).get_attribute("href") == "https://example.com/"


def test_sets_alt_text(page: Page) -> None:
    """
    If the image entity has alt text, it's added as an `alt` attribute
    on the `<img>` element.
    """
    e = create_image_entity(
        path="tests/fixtures/media/470906.png", alt_text="Some coloured red squares"
    )
    page.evaluate(
        """
        const elem = document.createElement("chives-image");
        elem.imageEntity = %s;
        document.body.appendChild(elem);
        """
        % json.dumps(e),
    )

    chives_elem = page.locator("chives-image")

    img_elem = chives_elem.locator("img")
    expect(img_elem).to_be_visible()
    assert (img_elem).get_attribute("alt") == "Some coloured red squares"


@pytest.mark.parametrize(
    "path, orientation",
    [
        ("tests/fixtures/media/470906.png", "square"),
        ("tests/fixtures/media/Landscape_0.jpg", "landscape"),
        ("tests/fixtures/media/Portrait_0.jpg", "portrait"),
    ],
)
def test_sets_orientation(page: Page, path: str, orientation: str) -> None:
    """
    The <chives-image> element sets a data-orientation attribute.
    """
    e = create_image_entity(path)
    page.evaluate(
        """
        const elem = document.createElement("chives-image");
        elem.imageEntity = %s;
        document.body.appendChild(elem);
        """
        % json.dumps(e),
    )

    chives_elem = page.locator("chives-image")

    wrapper_elem = chives_elem.locator("div")
    expect(wrapper_elem).to_be_visible()
    assert (wrapper_elem).get_attribute("data-orientation") == orientation


def test_animated_gif(page: Page) -> None:
    """
    The <chives-image> element can render an animated GIF.
    """
    e = create_image_entity("tests/fixtures/media/electric_field.gif")
    page.evaluate(
        """
        const elem = document.createElement("chives-image");
        elem.imageEntity = %s;
        document.body.appendChild(elem);
        """
        % json.dumps(e),
    )

    chives_elem = page.locator("chives-image")

    img_elem = chives_elem.locator("img")
    expect(img_elem).to_be_visible()
    assert (img_elem).get_attribute("src") == e["path"]


def test_animated_gif_with_video_thumbnail(page: Page, tmp_path: Path) -> None:
    """
    The <chives-image> element can render an animated GIF which has
    an MP4 thumbnail.
    """
    e = create_image_entity(
        "tests/fixtures/media/electric_field.gif",
        thumbnail_config={
            "out_dir": tmp_path,
            "width": 25,
        },
    )
    page.evaluate(
        """
        const elem = document.createElement("chives-image");
        elem.imageEntity = %s;
        elem.variant = 'thumbnail';
        document.body.appendChild(elem);
        """
        % json.dumps(e),
    )

    chives_elem = page.locator("chives-image")

    video_elem = chives_elem.locator("video")
    expect(video_elem).to_be_visible()
    assert (video_elem).get_attribute("src") == e["thumbnail_path"]
