import pytest

import responses
from django.core.files.uploadedfile import SimpleUploadedFile
from docutils.nodes import document
from inmemorystorage.storage import InMemoryFile

from django_docutils.favicon.prefetch import (
    is_favicon_stored,
    prefetch_favicon,
    yield_page_doctrees,
    yield_references,
)
from django_docutils.lib.publisher import publish_doctree

TEST_RST_DOCUMENT = """
Developing
==========

- Make a hobby website in django or flask.

  Services like `Heroku`_ are free to try, and simple to deploy Django
  websites to.

- For free editors, check out good old `vim`_, `Visual Studio Code`_,
  `Atom`_, or `PyCharm`_

.. _Visual Studio Code: https://code.visualstudio.com/
.. _Atom: https://atom.io/
.. _vim: http://vim.org
.. _PyCharm: https://www.jetbrains.com/pycharm/
"""

skip_or_deps = pytest.importorskip("tldextract") and pytest.importorskip("tqdm")


def test_yield_references():
    document = publish_doctree(TEST_RST_DOCUMENT)
    assert set(yield_references(document)) == {
        "https://code.visualstudio.com/",
        "https://atom.io/",
        "http://vim.org",
        "https://www.jetbrains.com/pycharm/",
    }


def test_yield_references_patterns():
    document = publish_doctree(TEST_RST_DOCUMENT)
    assert set(yield_references(document, url_pattern="atom")) == {"https://atom.io/"}


@pytest.mark.django_db(transaction=True)
def test_yield_page_doctrees(RSTPostPage):
    RSTPostPage.objects.create(subtitle="lol", body=TEST_RST_DOCUMENT)
    assert RSTPostPage.objects.filter(subtitle="lol").count()

    page_doctrees = list(yield_page_doctrees(RSTPostPage))
    assert len(page_doctrees)

    for page in page_doctrees:
        assert isinstance(page, document)


@pytest.mark.django_db(transaction=True)
@responses.activate
def test_prefetch_favicon_working():
    url = "http://vim.org"
    favicon_url = f"{url}/images/favicon.ico"
    favicon_content = b"lol"

    responses.add(
        responses.GET,
        url,
        body='<link rel="shortcut icon" href="{favicon_url}" />'.format(
            favicon_url=favicon_url
        ),
        status=200,
        content_type="text/html",
    )

    responses.add(
        responses.GET,
        favicon_url,
        body=favicon_content,
        status=200,
        content_type="image/ico",
    )

    favicon, created = prefetch_favicon(url)

    assert favicon.favicon.read() == favicon_content


@pytest.mark.django_db(transaction=True)
@responses.activate
def test_prefetch_favicon_file_missing(monkeypatch):
    # case where the favicon is in ORM, but file not in storage
    url = "http://vim.org"
    favicon_url = f"{url}/images/favicon.ico"
    favicon_content = b"lol"

    responses.add(
        responses.GET,
        url,
        body='<link rel="shortcut icon" href="{favicon_url}" />'.format(
            favicon_url=favicon_url
        ),
        status=200,
        content_type="text/html",
    )

    responses.add(
        responses.GET,
        favicon_url,
        body=favicon_content,
        status=200,
        content_type="image/ico",
    )

    def mock_file():
        raise FileNotFoundError

    favicon, created = prefetch_favicon(url)

    import django_docutils.favicon.prefetch

    assert not prefetch_favicon(url)
    monkeypatch.setattr(
        django_docutils.favicon.prefetch, "is_favicon_stored", lambda fqdn: False
    )

    favicon, created = prefetch_favicon(url)
    assert not created


@pytest.mark.django_db(transaction=True)
@responses.activate
def test_is_favicon_stored_file_missing(monkeypatch, Favicon):
    # case where the favicon is in ORM, but file not in storage
    url = "http://vim.org"
    fqdn = "vim.org"

    def mock_open(path, mode="r"):
        raise FileNotFoundError

    favicon = Favicon.objects.create(
        domain=fqdn,
        favicon=SimpleUploadedFile(
            name=f"{fqdn}.ico",
            content=b"lol",
            content_type="image/ico",
        ),
    )

    assert not prefetch_favicon(url), "File should not redownload"

    monkeypatch.setattr(InMemoryFile, "open", mock_open)
    with pytest.raises(FileNotFoundError):  # Assure monkeypatch
        favicon.favicon.file

    assert not is_favicon_stored(
        favicon.domain
    ), "favicon missing from storage should return False"


@pytest.mark.django_db(transaction=True)
@responses.activate
def test_is_favicon_stored_favicon_not_in_db(monkeypatch):
    assert not is_favicon_stored(
        "nonexistant_fqdn.com"
    ), "favicon missing from database should return False"
