import pytest
from unittest.mock import MagicMock
from datetime import datetime
from app.services.answer_service import AnswerService
from app.schemas.requests import UserAnswerSchema, AnswerItemSchema
from app.models.entities import QuestionItemEntity
from app.models import UserAnswerEntity
from app.exception import ValidationException


@pytest.fixture
def mock_answer_repository():
    return MagicMock()


@pytest.fixture
def mock_quiz_repository():
    return MagicMock()


@pytest.fixture
def mock_user_repository():
    return MagicMock()


@pytest.fixture
def answer_service(mock_answer_repository, mock_quiz_repository, mock_user_repository):
    return AnswerService(
        answer_repository=mock_answer_repository,
        quiz_repository=mock_quiz_repository,
        user_repositroy=mock_user_repository,
    )


def test_create_answer_success(
    answer_service, mock_quiz_repository, mock_user_repository, mock_answer_repository
):
    # Setup dummy quiz
    mock_quiz = MagicMock()
    mock_quiz.id = "quiz1"
    mock_quiz.total_user_playing = 5
    mock_quiz.question_listings = [
        QuestionItemEntity(
            index=0,
            question="Soal 1",
            type="fill_the_blank",
            target_answer="Jakarta",
            duration=10,
            options=[],
        ),
        QuestionItemEntity(
            index=1,
            question="Soal 2",
            type="true_false",
            target_answer="True",
            duration=10,
            options=[],
        ),
        QuestionItemEntity(
            index=2,
            question="Soal 3",
            type="option",
            target_answer="1",
            duration=10,
            options=["A", "B", "C"],
        ),
    ]
    mock_quiz_repository.get_by_id.return_value = mock_quiz

    # Setup dummy user
    mock_user_repository.get_user_by_id.return_value = MagicMock()

    # Setup user answer input
    answer_data = UserAnswerSchema(
        session_id="session1",
        quiz_id="quiz1",
        user_id="user1",
        answered_at=datetime.now(),
        answers=[
            AnswerItemSchema(
                question_index=0,
                answer="Jakarta",
                time_spent=10,
                is_correct=True,
            ),
            AnswerItemSchema(
                question_index=1,
                answer="True",
                time_spent=5,
                is_correct=True,
            ),
            AnswerItemSchema(
                question_index=2,
                answer="1",
                time_spent=7,
                is_correct=True,
            ),
        ],
    )

    mock_answer_repository.create.return_value = "answer_id_123"

    result = answer_service.create_answer(answer_data)

    assert result == "answer_id_123"
    mock_quiz_repository.update_user_playing.assert_called_once_with(
        quiz_id="quiz1", total_user=6
    )
    mock_answer_repository.create.assert_called_once()
    assert all([a.is_correct is not None for a in answer_data.answers])


def test_create_answer_quiz_not_found(answer_service, mock_quiz_repository):
    mock_quiz_repository.get_by_id.return_value = None

    answer_data = UserAnswerSchema(
        session_id="s1",
        quiz_id="nonexistent",
        user_id="u1",
        answered_at=datetime.now(),
        answers=[],
    )

    with pytest.raises(ValidationException, match="Quiz not found"):
        answer_service.create_answer(answer_data)


def test_create_answer_user_not_found(
    answer_service, mock_quiz_repository, mock_user_repository
):
    mock_quiz_repository.get_by_id.return_value = MagicMock()
    mock_user_repository.get_user_by_id.return_value = None

    answer_data = UserAnswerSchema(
        session_id="s1",
        quiz_id="q1",
        user_id="unknown_user",
        answered_at=datetime.now(),
        answers=[],
    )

    with pytest.raises(ValidationException, match="user is not registered"):
        answer_service.create_answer(answer_data)


def test_create_answer_invalid_option_index(
    answer_service, mock_quiz_repository, mock_user_repository
):
    quiz = MagicMock()
    quiz.id = "quiz1"
    quiz.total_user_playing = 0
    quiz.question_listings = [
        QuestionItemEntity(
            index=0,
            question="Soal 1",
            type="option",
            target_answer="1",
            duration=10,
            options=["A", "B", "C"],
        ),
    ]
    mock_quiz_repository.get_by_id.return_value = quiz
    mock_user_repository.get_user_by_id.return_value = MagicMock()

    answer_data = UserAnswerSchema(
        session_id="s1",
        quiz_id="quiz1",
        user_id="user1",
        answered_at=datetime.now(),
        answers=[
            AnswerItemSchema(
                question_index=0, answer="5", time_spent=3, is_correct=False
            )
        ],
    )

    with pytest.raises(ValueError, match="Index jawaban tidak valid"):
        answer_service.create_answer(answer_data)
