"""
Test Out Resource

PowerPath self-elected test-out operations.
"""

from __future__ import annotations

from typing import TYPE_CHECKING, Any
from urllib.parse import quote

from timeback_common import serialize_input, validate_non_empty_string, validate_with_schema

from ..types.inputs import MakeExternalStudentTestOutAssignmentInput
from ..types.responses import (
    GetTestOutEligibilityResponse,
    MakeExternalStudentTestOutAssignmentResponse,
)

if TYPE_CHECKING:
    from ..lib.transport import Transport


class TestOutResource:
    """Test out resource for self-elected test-out eligibility and assignment creation."""

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

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

    async def get_eligibility(self, student_id: str, subject: str) -> GetTestOutEligibilityResponse:
        """
        Check if a student is eligible to self-request a test-out for a subject.

        Args:
            student_id: The student's OneRoster sourcedId
            subject: The subject to check eligibility for

        Returns:
            Eligibility status and optional reason
        """
        validate_non_empty_string(student_id, "student_id")
        validate_non_empty_string(subject, "subject")
        body = await self._transport.get(
            f"{self._base_path}/test-out/getTestOutEligibility/{quote(student_id, safe='')}/{quote(subject, safe='')}"
        )
        return GetTestOutEligibilityResponse.model_validate(body)

    async def create_assignment(
        self, input: MakeExternalStudentTestOutAssignmentInput | dict[str, Any]
    ) -> MakeExternalStudentTestOutAssignmentResponse:
        """
        Create a self-elected test-out assignment.

        Args:
            input: Assignment data including one_roster_sourced_id and subject

        Returns:
            Success status and optional data
        """
        validate_with_schema(
            MakeExternalStudentTestOutAssignmentInput,
            input,
            "make external student test out assignment",
        )
        body = await self._transport.post(
            f"{self._base_path}/test-out/makeExternalStudentTestOutAssignment",
            serialize_input(input, MakeExternalStudentTestOutAssignmentInput),
        )
        return MakeExternalStudentTestOutAssignmentResponse.model_validate(body)
