"""
Assessment Resource

PowerPath assessment operations: tests, attempts, and responses.
"""

from __future__ import annotations

from typing import TYPE_CHECKING, Any

from timeback_common import serialize_input, validate_with_schema

from ..types.inputs import (
    CreateExternalPlacementTestInput,
    CreateExternalTestOutInput,
    CreateInternalTestInput,
    CreateNewAttemptInput,
    FinalStudentAssessmentResponseInput,
    GetAssessmentProgressParams,
    GetAttemptsParams,
    GetNextQuestionParams,
    ImportExternalTestAssignmentResultsParams,
    MakeExternalTestAssignmentInput,
    ResetAttemptInput,
    TestOutParams,
    UpdateStudentQuestionResponseInput,
)
from ..types.responses import (
    CreateAttemptResponse,
    ExternalTestCreateResponse,
    FinalizeAssessmentResponse,
    GetAssessmentProgressResponse,
    GetAttemptsResponse,
    GetNextQuestionResponse,
    ImportExternalResultsResponse,
    InternalTestCreateResponse,
    MakeExternalTestAssignmentResponse,
    ResetAttemptResponse,
    TestOutResponse,
    UpdateStudentQuestionResponseResult,
)

if TYPE_CHECKING:
    from ..lib.transport import Transport


class AssessmentResource:
    """Assessment resource for PowerPath operations."""

    def __init__(self, transport: Transport) -> None:
        self._transport = transport

    @property
    def _base_path(self) -> str:
        return self._transport.paths.base

    async def create_external_placement_test(
        self, input: CreateExternalPlacementTestInput | dict[str, Any]
    ) -> ExternalTestCreateResponse:
        """Create an external placement test."""
        validate_with_schema(
            CreateExternalPlacementTestInput, input, "create external placement test"
        )
        body = await self._transport.post(
            f"{self._base_path}/createExternalPlacementTest",
            serialize_input(input, CreateExternalPlacementTestInput),
        )
        return ExternalTestCreateResponse.model_validate(body)

    async def create_external_test_out(
        self, input: CreateExternalTestOutInput | dict[str, Any]
    ) -> ExternalTestCreateResponse:
        """Create an external test-out."""
        validate_with_schema(CreateExternalTestOutInput, input, "create external test out")
        body = await self._transport.post(
            f"{self._base_path}/createExternalTestOut",
            serialize_input(input, CreateExternalTestOutInput),
        )
        return ExternalTestCreateResponse.model_validate(body)

    async def create_internal_test(
        self, input: CreateInternalTestInput | dict[str, Any]
    ) -> InternalTestCreateResponse:
        """Create an internal test (QTI or assessment-bank)."""
        validate_with_schema(CreateInternalTestInput, input, "create internal test")
        body = await self._transport.post(
            f"{self._base_path}/createInternalTest",
            serialize_input(input, CreateInternalTestInput),
        )
        return InternalTestCreateResponse.model_validate(body)

    async def create_new_attempt(
        self, input: CreateNewAttemptInput | dict[str, Any]
    ) -> CreateAttemptResponse:
        """Create a new attempt for a lesson."""
        validate_with_schema(CreateNewAttemptInput, input, "create new attempt")
        body = await self._transport.post(
            f"{self._base_path}/createNewAttempt",
            serialize_input(input, CreateNewAttemptInput),
        )
        return CreateAttemptResponse.model_validate(body)

    async def final_student_assessment_response(
        self, input: FinalStudentAssessmentResponseInput | dict[str, Any]
    ) -> FinalizeAssessmentResponse:
        """Finalize a student assessment response."""
        validate_with_schema(
            FinalStudentAssessmentResponseInput, input, "final student assessment response"
        )
        body = await self._transport.post(
            f"{self._base_path}/finalStudentAssessmentResponse",
            serialize_input(input, FinalStudentAssessmentResponseInput),
        )
        return FinalizeAssessmentResponse.model_validate(body)

    async def get_assessment_progress(
        self, params: GetAssessmentProgressParams | dict[str, Any]
    ) -> GetAssessmentProgressResponse:
        """Get assessment progress (PowerPath100 or standard quiz-like)."""
        validate_with_schema(GetAssessmentProgressParams, params, "get assessment progress params")
        from pydantic import TypeAdapter

        body = await self._transport.get(
            f"{self._base_path}/getAssessmentProgress",
            params=serialize_input(params, GetAssessmentProgressParams),
        )
        adapter: TypeAdapter[GetAssessmentProgressResponse] = TypeAdapter(
            GetAssessmentProgressResponse
        )
        return adapter.validate_python(body)

    async def get_attempts(self, params: GetAttemptsParams | dict[str, Any]) -> GetAttemptsResponse:
        """Get attempts for a lesson."""
        validate_with_schema(GetAttemptsParams, params, "get attempts params")
        body = await self._transport.get(
            f"{self._base_path}/getAttempts",
            params=serialize_input(params, GetAttemptsParams),
        )
        return GetAttemptsResponse.model_validate(body)

    async def get_next_question(
        self, params: GetNextQuestionParams | dict[str, Any]
    ) -> GetNextQuestionResponse:
        """Get the next question in a PowerPath 100 lesson."""
        validate_with_schema(GetNextQuestionParams, params, "get next question params")
        body = await self._transport.get(
            f"{self._base_path}/getNextQuestion",
            params=serialize_input(params, GetNextQuestionParams),
        )
        return GetNextQuestionResponse.model_validate(body)

    async def import_external_test_assignment_results(
        self, params: ImportExternalTestAssignmentResultsParams | dict[str, Any]
    ) -> ImportExternalResultsResponse:
        """Import external test assignment results."""
        validate_with_schema(
            ImportExternalTestAssignmentResultsParams,
            params,
            "import external test assignment results params",
        )
        body = await self._transport.get(
            f"{self._base_path}/importExternalTestAssignmentResults",
            params=serialize_input(params, ImportExternalTestAssignmentResultsParams),
        )
        return ImportExternalResultsResponse.model_validate(body)

    async def make_external_test_assignment(
        self, input: MakeExternalTestAssignmentInput | dict[str, Any]
    ) -> MakeExternalTestAssignmentResponse:
        """Assign an external test to a student."""
        validate_with_schema(
            MakeExternalTestAssignmentInput, input, "make external test assignment"
        )
        body = await self._transport.post(
            f"{self._base_path}/makeExternalTestAssignment",
            serialize_input(input, MakeExternalTestAssignmentInput),
        )
        return MakeExternalTestAssignmentResponse.model_validate(body)

    async def reset_attempt(
        self, input: ResetAttemptInput | dict[str, Any]
    ) -> ResetAttemptResponse:
        """Reset an attempt."""
        validate_with_schema(ResetAttemptInput, input, "reset attempt")
        body = await self._transport.post(
            f"{self._base_path}/resetAttempt",
            serialize_input(input, ResetAttemptInput),
        )
        return ResetAttemptResponse.model_validate(body)

    async def test_out(self, params: TestOutParams | dict[str, Any]) -> TestOutResponse:
        """Get the test-out lesson for a student/course."""
        validate_with_schema(TestOutParams, params, "test out params")
        body = await self._transport.get(
            f"{self._base_path}/testOut",
            params=serialize_input(params, TestOutParams),
        )
        return TestOutResponse.model_validate(body)

    async def update_student_question_response(
        self, input: UpdateStudentQuestionResponseInput | dict[str, Any]
    ) -> UpdateStudentQuestionResponseResult:
        """Update a student question response (PowerPath100 or standard quiz-like)."""
        validate_with_schema(
            UpdateStudentQuestionResponseInput, input, "update student question response"
        )
        from pydantic import TypeAdapter

        body = await self._transport.put(
            f"{self._base_path}/updateStudentQuestionResponse",
            serialize_input(input, UpdateStudentQuestionResponseInput),
        )
        adapter: TypeAdapter[UpdateStudentQuestionResponseResult] = TypeAdapter(
            UpdateStudentQuestionResponseResult
        )
        return adapter.validate_python(body)
