"""
Qué error detiene un lote de indexación y cuál sólo marca una URL.

La regla que decidió el owner es «apenas Google responda mal, se corta», con una
única excepción: cuando el problema es de *esa* dirección y no del canal.
Frenar un lote de quinientas URLs porque una estaba mal escrita deja
cuatrocientas noventa y nueve sin enviar por algo que no las afecta.

La distinción vive acá y en un solo lugar. Repartida entre la tarea y la
pantalla es de la clase de regla que se afloja: alguien agrega un código nuevo
en un lado y el otro sigue tratándolo como antes.

**Este módulo no aplica ningún tope propio de cuota.** La app envía hasta que
Google diga basta, y su respuesta —guardada cruda— es la prueba de que el límite
existe. Un contador nuestro sería una afirmación de la app sobre cuánto se
puede; el error de Google es un documento de Google.
"""

from apps.gsc.errors import GoogleErrorCode, classify


class IndexingErrorCode:
    """
    Códigos propios de la indexación, sobre los de `apps.gsc.errors`.

    Sólo agrega el que allá no existe. Reutilizar el resto no es ahorro de
    tipeo: es lo que hace que la pantalla de errores de Google sea una sola y no
    dos que hay que mantener parejas.
    """

    #: Google rechazó *esta* dirección. Mal formada, ajena a la propiedad, o
    #: inexistente para él. No dice nada sobre las que vienen detrás.
    URL_REJECTED = 'URL_REJECTED'


#: Lo único que no corta el lote.
#:
#: Se escribe por la afirmativa —qué deja seguir— y no por la negativa, porque
#: la lista tiene que fallar hacia el lado seguro: un código nuevo que nadie
#: clasificó corta, en vez de dejar corriendo un lote contra una API que ya
#: contestó mal cuatrocientas veces.
CONTINUING_CODES = frozenset({IndexingErrorCode.URL_REJECTED})

MESSAGES = {
    IndexingErrorCode.URL_REJECTED: (
        'Google rechazó esta dirección. Puede estar mal formada, no pertenecer a la '
        'propiedad o no existir para él. Las demás del lote siguen.'
    ),
}


def classify_indexing(status: int | None, body: str = '') -> str:
    """
    Elige el motivo de un fallo de la Indexing API.

    Se apoya en la clasificación de Search Console y sólo corrige lo que ahí
    significa otra cosa. Un 404 de Search Console es «esa propiedad no existe en
    tu cuenta»; un 404 de indexación es «esa dirección», que es un problema de
    alcance mucho más chico y que no condena al resto del lote.
    """
    if status in (400, 404):
        return IndexingErrorCode.URL_REJECTED

    return classify(status, body)


def cuts_the_batch(code: str) -> bool:
    """Si este error obliga a detener el lote donde está."""
    return code not in CONTINUING_CODES


def message_for(code: str) -> str:
    """La explicación del código, para la evidencia y para el resumen del lote."""
    from apps.gsc.errors import MESSAGES as GOOGLE_MESSAGES

    if code in MESSAGES:
        return MESSAGES[code]
    return GOOGLE_MESSAGES.get(code, GOOGLE_MESSAGES[GoogleErrorCode.UNEXPECTED])
