from fastapi.testclient import TestClient
from sqlmodel import Session, select

from app.db.session import engine
from app.main import app
from app.models import CoinTransaction, DailyPhrase, DailyPhraseSlotAssignment, PhraseQuizSlotAttempt

client = TestClient(app)


def test_daily_phrase_assignments_are_language_specific_stable_and_slot_based():
    first = client.get('/api/daily-phrases', params={'date': '2026-06-16', 'slot': '06:00'})
    second = client.get('/api/daily-phrases', params={'date': '2026-06-16', 'slot': '06:00'})
    noon = client.get('/api/daily-phrases', params={'date': '2026-06-16', 'slot': '11:00'})
    assert first.status_code == 200
    assert second.status_code == 200
    assert noon.status_code == 200
    assert first.json()['slot'] == '06:00'
    assert noon.json()['slot'] == '11:00'
    items = first.json()['items']
    assert {item['child_name'] for item in items} == {'Emilia', 'Valerie'}
    by_child = {item['child_name']: item for item in items}
    assert by_child['Valerie']['phrase']['language'] == 'en'
    assert by_child['Emilia']['phrase']['language'] == 'fr'
    assert by_child['Valerie']['phrase']['foreign_text'] != by_child['Emilia']['phrase']['foreign_text']
    assert first.json() == second.json()
    assert {item['slot'] for item in noon.json()['items']} == {'11:00'}

    with Session(engine) as session:
        assert len(session.exec(select(DailyPhraseSlotAssignment)).all()) == 4
        assert len(session.exec(select(DailyPhrase).where(DailyPhrase.language == 'en')).all()) >= 30
        assert len(session.exec(select(DailyPhrase).where(DailyPhrase.language == 'fr')).all()) >= 30


def test_daily_phrase_quiz_correct_answer_awards_one_coin_once():
    quiz = client.get('/api/daily-phrases/quiz', params={'date': '2026-06-16', 'slot': '15:00'})
    assert quiz.status_code == 200
    item = quiz.json()['items'][0]
    with Session(engine) as session:
        phrase = session.get(DailyPhrase, item['phrase']['id'])
        correct = phrase.german_translation
    response = client.post('/api/daily-phrases/quiz-answer', json={
        'child_id': item['child_id'],
        'date': item['date'],
        'slot': item['slot'],
        'phrase_id': item['phrase']['id'],
        'selected_answer': correct,
    })
    assert response.status_code == 200
    assert response.json()['correct'] is True
    assert response.json()['coin_awarded'] is True

    duplicate = client.post('/api/daily-phrases/quiz-answer', json={
        'child_id': item['child_id'],
        'date': item['date'],
        'slot': item['slot'],
        'phrase_id': item['phrase']['id'],
        'selected_answer': correct,
    })
    assert duplicate.status_code == 200
    assert duplicate.json()['coin_awarded'] is False
    assert duplicate.json()['idempotent'] is True

    again = client.get('/api/daily-phrases/quiz', params={'date': '2026-06-16', 'slot': '15:00'}).json()
    stored = next(row for row in again['items'] if row['child_id'] == item['child_id'])
    assert stored['answered'] is True
    assert stored['attempt']['selected_answer'] == correct
    with Session(engine) as session:
        assert len(session.exec(select(PhraseQuizSlotAttempt)).all()) == 1
        txs = session.exec(select(CoinTransaction).where(CoinTransaction.child_id == item['child_id'])).all()
        assert sum(tx.amount for tx in txs if tx.comment.startswith('Satz des Tages')) == 1


def test_wrong_daily_phrase_answer_does_not_award_coin():
    quiz = client.get('/api/daily-phrases/quiz', params={'date': '2026-06-17', 'slot': '06:00'})
    item = quiz.json()['items'][0]
    with Session(engine) as session:
        phrase = session.get(DailyPhrase, item['phrase']['id'])
        wrong = phrase.wrong_option_1
    response = client.post('/api/daily-phrases/quiz-answer', json={
        'child_id': item['child_id'],
        'date': item['date'],
        'slot': item['slot'],
        'phrase_id': item['phrase']['id'],
        'selected_answer': wrong,
    })
    assert response.status_code == 200
    assert response.json()['correct'] is False
    assert response.json()['coin_awarded'] is False
    with Session(engine) as session:
        txs = session.exec(select(CoinTransaction).where(CoinTransaction.child_id == item['child_id'])).all()
        assert not any(tx.comment.startswith('Satz des Tages') for tx in txs)
