"""
Traducción del veredicto de Google (R4).

La regla que se verifica una y otra vez acá es la asimetría: **sólo `PASS` es
indexada**, y lo que no se reconoce cae en «sin indexar, otro motivo», jamás en
«sin consultar». Decir «no sabemos» de algo que Google contestó esconde una
respuesta real; decir «indexada» de algo que no lo está manda a alguien a no
revisar una página que necesitaba revisión.
"""

import pytest

from apps.coverage.translation import raw_fields, translate
from apps.sitemaps.models import CoverageState
from tests.doubles import response


def _index_status(name: str) -> dict:
    return response(name)['inspectionResult']['indexStatusResult']


def test_only_the_pass_verdict_counts_as_indexed():
    assert translate(_index_status('url_inspection_indexada')) == CoverageState.INDEXED


def test_a_verdict_other_than_pass_is_never_indexed():
    """
    Aunque el resto de los campos parezcan buenos.

    Es el caso más peligroso: rastreada, permitida por robots, descargada sin
    error. Todo verde salvo el veredicto. Sin esta regla, la página figuraría
    como indexada sin estarlo.
    """
    state = translate(
        {
            'verdict': 'NEUTRAL',
            'coverageState': 'Crawled - currently not indexed',
            'robotsTxtState': 'ALLOWED',
            'indexingState': 'INDEXING_ALLOWED',
            'pageFetchState': 'SUCCESSFUL',
        }
    )
    assert state == CoverageState.CRAWLED_NOT_INDEXED


def test_a_state_google_did_not_document_falls_into_the_generic_one_and_not_into_unknown():
    state = translate(_index_status('url_inspection_estado_desconocido'))

    assert state == CoverageState.OTHER_NOT_INDEXED
    # Éste es el punto: nunca UNKNOWN. UNKNOWN significa «no preguntamos», y acá
    # sí preguntamos: Google contestó algo que no supimos clasificar.
    assert state != CoverageState.UNKNOWN


def test_an_empty_response_does_not_produce_unknown_either():
    assert translate({}) == CoverageState.OTHER_NOT_INDEXED
    assert translate(None) == CoverageState.OTHER_NOT_INDEXED


@pytest.mark.parametrize(
    ('coverage_state', 'expected'),
    [
        ('Crawled - currently not indexed', CoverageState.CRAWLED_NOT_INDEXED),
        ('Discovered - currently not indexed', CoverageState.DISCOVERED_NOT_INDEXED),
        ('Duplicate without user-selected canonical', CoverageState.DUPLICATE_CANONICAL),
        (
            'Duplicate, Google chose different canonical than user',
            CoverageState.DUPLICATE_CANONICAL,
        ),
        ('Alternate page with proper canonical tag', CoverageState.DUPLICATE_CANONICAL),
        ('Blocked by robots.txt', CoverageState.BLOCKED_ROBOTS),
        ('Page with redirect', CoverageState.REDIRECT),
        ('Not found (404)', CoverageState.FETCH_ERROR),
        ('Soft 404', CoverageState.FETCH_ERROR),
        ('Server error (5xx)', CoverageState.FETCH_ERROR),
    ],
)
def test_the_documented_states_are_translated(coverage_state, expected):
    assert translate({'verdict': 'NEUTRAL', 'coverageState': coverage_state}) == expected


# Las comillas tipográficas son el dato bajo prueba: Google escribe así el
# estado, y el linter no tiene forma de saberlo.
@pytest.mark.parametrize(
    'text',
    [
        'excluded by ‘noindex’ tag',  # noqa: RUF001
        "excluded by 'noindex' tag",
        'Excluded by ‘noindex’ tag',  # noqa: RUF001
    ],
)
def test_the_noindex_is_recognized_with_either_of_the_two_quotes(text):
    """
    Google escribe este estado con comilla tipográfica y a veces con la recta.

    Reconocer sólo una haría que el mismo estado se clasifique distinto según
    qué comilla mandó Google ese día.
    """
    assert translate({'verdict': 'FAIL', 'coverageState': text}) == CoverageState.EXCLUDED_NOINDEX


def test_the_reason_can_come_in_a_separate_field():
    """A veces el estado de cobertura no dice nada y la razón está en otro campo."""
    state = translate({'verdict': 'FAIL', 'coverageState': '', 'robotsTxtState': 'DISALLOWED'})
    assert state == CoverageState.BLOCKED_ROBOTS


def test_the_raw_fields_are_kept_so_that_recalculation_is_possible():
    """
    Guardar el dato original es lo que permite corregir la traducción sin cuota.

    Si mañana entendemos mejor un estado, se recalcula todo el historial sin
    volver a preguntarle nada a Google.
    """
    raw = raw_fields(_index_status('url_inspection_indexada'))

    assert raw['raw_verdict'] == 'PASS'
    assert raw['raw_coverage_state'] == 'Submitted and indexed'
    assert raw['google_canonical'] == 'https://ejemplo.test/pagina'


def test_the_raw_fields_tolerate_an_incomplete_response():
    raw = raw_fields({'verdict': 'FAIL'})

    assert raw['raw_verdict'] == 'FAIL'
    assert raw['raw_coverage_state'] == ''
    assert raw['google_canonical'] == ''
