"""
Lectura de sitemaps.

Se prueba contra archivos reales guardados en `tests/fixtures/sitemaps/`, no
contra XML armado en el test: la mitad de los problemas de esta pieza vienen de
cómo los sitios escriben de verdad sus sitemaps —espacios de nombres omitidos,
etiquetas de más, páginas de error servidas con un 200— y un XML fabricado a
medida nunca los reproduce.
"""

from pathlib import Path

import pytest
from django.conf import settings

from apps.sitemaps.reader import SitemapUnreadable, parse

FIXTURES = Path(settings.BASE_DIR) / 'tests' / 'fixtures' / 'sitemaps'


def file(name: str) -> bytes:
    return (FIXTURES / name).read_bytes()


def test_a_list_of_urls_returns_its_locations():
    content = parse(file('urlset.xml'))

    assert content.is_index is False
    assert content.count == 3
    assert content.locations[0] == 'https://ejemplo.test/'
    assert 'https://ejemplo.test/nota/dos' in content.locations


def test_an_index_is_recognized_as_such():
    content = parse(file('indice.xml'))

    assert content.is_index is True
    assert content.locations == [
        'https://ejemplo.test/sitemap-1.xml',
        'https://ejemplo.test/sitemap-2.xml',
    ]


def test_a_sitemap_without_a_namespace_is_read_all_the_same():
    """
    El espacio de nombres es obligatorio en teoría y hay sitios que lo omiten.

    Rechazarlos no le sirve a nadie: el archivo se entiende perfectamente y el
    usuario no puede hacer nada al respecto si el sitemap lo genera su CMS.
    """
    content = parse(file('urlset_sin_espacio_de_nombres.xml'))

    assert content.locations == ['https://ejemplo.test/sin-ns']


def test_an_html_page_served_as_a_sitemap_says_so():
    """
    El caso más frecuente y el más confuso: la dirección devuelve HTML con un 200.

    «No es XML válido» a secas dejaría pensando que el sitemap está roto, cuando
    lo que pasa es que la dirección apunta a otra cosa.
    """
    with pytest.raises(SitemapUnreadable) as exc:
        parse(file('pagina_de_error.html'))

    assert 'no es XML válido' in str(exc.value) or 'se esperaba' in str(exc.value)


def test_an_xml_with_another_root_says_which_one_it_found():
    with pytest.raises(SitemapUnreadable) as exc:
        parse(b'<?xml version="1.0"?><rss><channel/></rss>')

    assert 'rss' in str(exc.value)
    assert 'urlset' in str(exc.value)


def test_the_content_hash_changes_when_the_sitemap_changes():
    """
    Es la base de no reenviar a Google lo mismo todos los días.

    Reenviar un sitemap idéntico no le aporta nada y gasta cupo del dominio, que
    después falta para consultar cobertura.
    """
    one = parse(file('urlset.xml'))
    another = parse(file('urlset.xml').replace(b'/nota/dos', b'/nota/tres'))

    assert one.content_hash != another.content_hash
    assert parse(file('urlset.xml')).content_hash == one.content_hash
