"""Tests for Canvas Question Bank quiz helpers."""

import os
import sys
import unittest
from unittest.mock import MagicMock, patch

sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "scripts"))

import canvas_api


def _mock_config():
    return {
        "token": "fake",
        "domain": "canvas.test.edu",
        "course_id": "99999",
        "base_url": "https://canvas.test.edu/api/v1",
        "course_url": "https://canvas.test.edu/api/v1/courses/99999",
        "headers": {"Authorization": "Bearer fake"},
    }


def _response(status_code, payload=None, text=""):
    resp = MagicMock()
    resp.status_code = status_code
    resp.text = text
    resp.json.return_value = payload if payload is not None else {}
    return resp


class TestQuestionBanks(unittest.TestCase):
    @patch("canvas_api._request_with_retry")
    def test_get_question_bank_returns_dict_on_200(self, mock_request):
        bank = {
            "id": 333,
            "title": "Midterm Bank",
            "assessment_question_count": 12,
        }
        mock_request.return_value = _response(200, bank)

        result = canvas_api.get_question_bank(_mock_config(), 333)

        self.assertEqual(result, bank)
        args = mock_request.call_args.args
        self.assertIs(args[0], canvas_api.requests.get)
        self.assertEqual(
            args[1],
            "https://canvas.test.edu/api/v1/courses/99999/question_banks/333",
        )

    @patch("canvas_api._request_with_retry")
    def test_get_question_bank_returns_none_on_404(self, mock_request):
        mock_request.return_value = _response(404, text="not found")

        result = canvas_api.get_question_bank(_mock_config(), 333)

        self.assertIsNone(result)

    @patch("canvas_api._request_with_retry")
    def test_add_question_from_bank_posts_form_encoded_body(self, mock_request):
        question = {"id": 444, "position": 2}
        mock_request.return_value = _response(200, question)

        result = canvas_api.add_question_from_bank(
            _mock_config(), quiz_id=222, question_bank_id=333, position=2)

        self.assertEqual(result, question)
        args = mock_request.call_args.args
        kwargs = mock_request.call_args.kwargs
        self.assertIs(args[0], canvas_api.requests.post)
        self.assertEqual(
            args[1],
            "https://canvas.test.edu/api/v1/courses/99999/quizzes/222/questions",
        )
        self.assertEqual(kwargs["data"], {
            "question[question_bank_id]": 333,
            "question[position]": 2,
        })
        self.assertNotIn("json", kwargs)

    @patch("canvas_api._request_with_retry")
    def test_create_quiz_group_posts_quiz_groups_json_body(self, mock_request):
        group = {
            "id": 555,
            "name": "Randomized Bank Pull",
            "pick_count": 10,
            "question_points": 2,
            "assessment_question_bank_id": 333,
        }
        mock_request.return_value = _response(200, {"quiz_groups": [group]})

        result = canvas_api.create_quiz_group(
            _mock_config(),
            quiz_id=222,
            name="Randomized Bank Pull",
            pick_count=10,
            question_points=2,
            assessment_question_bank_id=333,
        )

        self.assertEqual(result, group)
        args = mock_request.call_args.args
        kwargs = mock_request.call_args.kwargs
        self.assertIs(args[0], canvas_api.requests.post)
        self.assertEqual(
            args[1],
            "https://canvas.test.edu/api/v1/courses/99999/quizzes/222/groups",
        )
        self.assertEqual(kwargs["json"], {
            "quiz_groups": [{
                "name": "Randomized Bank Pull",
                "pick_count": 10,
                "question_points": 2,
                "assessment_question_bank_id": 333,
            }]
        })

    @patch("canvas_api._request_with_retry")
    def test_build_quiz_from_bank_smoke_call_sequence(self, mock_request):
        call_sequence = []

        def fake_request(method, url, headers, **kwargs):
            if url.endswith("/question_banks/333"):
                call_sequence.append("get_question_bank")
                return _response(200, {
                    "id": 333,
                    "title": "Midterm Bank",
                    "assessment_question_count": 12,
                })
            if url.endswith("/quizzes") and method is canvas_api.requests.post:
                call_sequence.append("create_quiz")
                return _response(200, {"id": 222, "title": "Bank Quiz"})
            if url.endswith("/quizzes/222/groups"):
                call_sequence.append("create_quiz_group")
                return _response(200, {"quiz_groups": [{
                    "id": 555,
                    "name": "Bank Pull",
                    "pick_count": 5,
                    "question_points": 2,
                    "assessment_question_bank_id": 333,
                }]})
            raise AssertionError(f"Unexpected API call: {method} {url}")

        mock_request.side_effect = fake_request
        config = _mock_config()

        bank = canvas_api.get_question_bank(config, 333)
        quiz = canvas_api.create_quiz(
            config,
            "Bank Quiz",
            quiz_type="assignment",
            points_possible=10,
        )
        group = canvas_api.create_quiz_group(
            config,
            quiz["id"],
            "Bank Pull",
            pick_count=5,
            question_points=2,
            assessment_question_bank_id=bank["id"],
        )

        self.assertEqual(call_sequence, [
            "get_question_bank",
            "create_quiz",
            "create_quiz_group",
        ])
        self.assertEqual(group["assessment_question_bank_id"], 333)


if __name__ == "__main__":
    unittest.main()
