"""
Las reglas del generador que viven en TypeScript, ejercitadas en Node.

Lo que se defiende: que la pantalla muestre las mismas preguntas que el
servidor va a aceptar, que sepa qué falta antes de mandar, que un código de
error desconocido no rompa la pantalla, y que los cuatro estados se distingan
por silueta y tono, no sólo por color (RT-04).
"""

import re

import pytest

from tests.frontend.harness import call, needs_frontend, render, resolve

LABELS = '@/pages/Ai/ImageGenerator/labels'
BADGE = '@/components/GenerationStateBadge'

pytestmark = needs_frontend

POOL_QUESTIONS = [
    {'key': 'pool_shape', 'options': [{'code': 'lap', 'image': None}], 'shown_if': None},
    {
        'key': 'want_spa',
        'options': [{'code': 'yes', 'image': None}, {'code': 'no', 'image': None}],
        'shown_if': None,
    },
    {
        'key': 'spa_shape',
        'options': [{'code': 'square', 'image': None}],
        'shown_if': {'question': 'want_spa', 'option': 'yes'},
    },
    {'key': 'pool_finish', 'options': [{'code': 'tile', 'image': None}], 'shown_if': None},
]

REQUESTS = {
    'visible_without_spa': call(LABELS, 'visibleQuestions', POOL_QUESTIONS, {'want_spa': 'no'}),
    'visible_with_spa': call(LABELS, 'visibleQuestions', POOL_QUESTIONS, {'want_spa': 'yes'}),
    'unanswered': call(
        LABELS, 'unanswered', POOL_QUESTIONS, {'want_spa': 'yes', 'pool_shape': 'lap'}
    ),
    'unknown_error': call(LABELS, 'generationErrorText', 'SOMETHING_NEW'),
    'known_error': call(LABELS, 'generationErrorText', 'PROVIDER_NOT_CONFIGURED'),
    'badge_queued': render(BADGE, 'GenerationStateBadge', state='QUEUED'),
    'badge_running': render(BADGE, 'GenerationStateBadge', state='RUNNING'),
    'badge_completed': render(BADGE, 'GenerationStateBadge', state='COMPLETED'),
    'badge_failed': render(BADGE, 'GenerationStateBadge', state='FAILED'),
}


@pytest.fixture(scope='module')
def results():
    return resolve(REQUESTS)


def keys(questions):
    return [question['key'] for question in questions]


def test_a_conditioned_question_only_shows_with_its_answer(results):
    """La misma regla que aplica el servidor al limpiar las respuestas."""
    assert keys(results['visible_without_spa']) == ['pool_shape', 'want_spa', 'pool_finish']
    assert keys(results['visible_with_spa']) == [
        'pool_shape',
        'want_spa',
        'spa_shape',
        'pool_finish',
    ]


def test_what_is_missing_is_only_what_is_shown(results):
    assert results['unanswered'] == ['spa_shape', 'pool_finish']


def test_an_unknown_error_code_falls_back_instead_of_breaking(results):
    """Los códigos nacen en el servidor; un despliegue puede adelantarse al catálogo."""
    assert (
        results['unknown_error'] == results['known_error']
        or 'Something went wrong' in results['unknown_error']
    )
    assert 'OpenAI key' in results['known_error']


def tone(markup: str) -> str:
    match = re.search(r'data-tone="([a-z]+)"', markup)
    assert match, markup
    return match.group(1)


def test_the_four_states_carry_four_tones_and_their_word(results):
    assert tone(results['badge_queued']) == 'neutral'
    assert tone(results['badge_running']) == 'neutral'
    assert tone(results['badge_completed']) == 'positive'
    assert tone(results['badge_failed']) == 'critical'
    assert 'Queued' in results['badge_queued']
    assert 'Generating' in results['badge_running']
    assert 'Completed' in results['badge_completed']
    assert 'Failed' in results['badge_failed']


def test_only_the_running_state_moves(results):
    assert 'animate-spin' in results['badge_running']
    assert 'animate-spin' not in results['badge_queued']
