"""
Lesson Plans Resource

PowerPath lesson plan operations and progress tracking.
"""

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 (
    LessonPlanOperationsInput,
    LessonPlansCreateInput,
    LessonPlanUpdateStudentItemResponseInput,
)
from ..types.responses import (
    CourseProgressResponse,
    LessonPlanCourseSyncResult,
    LessonPlanCreateResponse,
    LessonPlanOperationResult,
    LessonPlanOperationsResponse,
    LessonPlanResponse,
    LessonPlanSyncResult,
    UpdateStudentItemResponseResult,
)

if TYPE_CHECKING:
    from ..lib.transport import Transport


class LessonPlansResource:
    """Lesson plans resource for managing course lesson plans and progress."""

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

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

    async def create(
        self, input: LessonPlansCreateInput | dict[str, Any]
    ) -> LessonPlanCreateResponse:
        """Create a lesson plan."""
        validate_with_schema(LessonPlansCreateInput, input, "lesson plan create")
        body = await self._transport.post(
            f"{self._base_path}/lessonPlans/",
            serialize_input(input, LessonPlansCreateInput),
        )
        return LessonPlanCreateResponse.model_validate(body)

    async def get(self, course_id: str, user_id: str) -> LessonPlanResponse:
        """Get a lesson plan for a course and user."""
        validate_non_empty_string(course_id, "course_id")
        validate_non_empty_string(user_id, "user_id")
        body = await self._transport.get(
            f"{self._base_path}/lessonPlans/{quote(course_id, safe='')}/{quote(user_id, safe='')}"
        )
        return LessonPlanResponse.model_validate(body)

    async def delete_all(self, course_id: str) -> None:
        """Delete all lesson plans for a course."""
        validate_non_empty_string(course_id, "course_id")
        await self._transport.delete(
            f"{self._base_path}/lessonPlans/{quote(course_id, safe='')}/deleteAll"
        )

    async def list_operations(self, lesson_plan_id: str) -> LessonPlanOperationsResponse:
        """List operations for a lesson plan."""
        validate_non_empty_string(lesson_plan_id, "lesson_plan_id")
        body = await self._transport.get(
            f"{self._base_path}/lessonPlans/{quote(lesson_plan_id, safe='')}/operations"
        )
        return LessonPlanOperationsResponse.model_validate(body)

    async def create_operations(
        self,
        lesson_plan_id: str,
        input: LessonPlanOperationsInput | dict[str, Any],
    ) -> LessonPlanOperationResult:
        """Create operations for a lesson plan."""
        validate_non_empty_string(lesson_plan_id, "lesson_plan_id")
        validate_with_schema(LessonPlanOperationsInput, input, "lesson plan operations")
        body = await self._transport.post(
            f"{self._base_path}/lessonPlans/{quote(lesson_plan_id, safe='')}/operations",
            serialize_input(input, LessonPlanOperationsInput),
        )
        return LessonPlanOperationResult.model_validate(body)

    async def sync(self, lesson_plan_id: str) -> LessonPlanSyncResult:
        """Sync lesson plan operations."""
        validate_non_empty_string(lesson_plan_id, "lesson_plan_id")
        body = await self._transport.post(
            f"{self._base_path}/lessonPlans/{quote(lesson_plan_id, safe='')}/operations/sync",
        )
        return LessonPlanSyncResult.model_validate(body)

    async def sync_course(self, course_id: str) -> LessonPlanCourseSyncResult:
        """Sync a course's lesson plans."""
        validate_non_empty_string(course_id, "course_id")
        body = await self._transport.post(
            f"{self._base_path}/lessonPlans/course/{quote(course_id, safe='')}/sync",
        )
        return LessonPlanCourseSyncResult.model_validate(body)

    async def recreate(self, lesson_plan_id: str) -> LessonPlanSyncResult:
        """Recreate a lesson plan."""
        validate_non_empty_string(lesson_plan_id, "lesson_plan_id")
        body = await self._transport.post(
            f"{self._base_path}/lessonPlans/{quote(lesson_plan_id, safe='')}/recreate",
        )
        return LessonPlanSyncResult.model_validate(body)

    async def get_course_progress(self, course_id: str, student_id: str) -> CourseProgressResponse:
        """Get course progress for a student."""
        validate_non_empty_string(course_id, "course_id")
        validate_non_empty_string(student_id, "student_id")
        body = await self._transport.get(
            f"{self._base_path}/lessonPlans/getCourseProgress"
            f"/{quote(course_id, safe='')}/student/{quote(student_id, safe='')}"
        )
        return CourseProgressResponse.model_validate(body)

    async def get_tree(self, lesson_plan_id: str) -> LessonPlanResponse:
        """Get the lesson plan tree."""
        validate_non_empty_string(lesson_plan_id, "lesson_plan_id")
        body = await self._transport.get(
            f"{self._base_path}/lessonPlans/tree/{quote(lesson_plan_id, safe='')}"
        )
        return LessonPlanResponse.model_validate(body)

    async def get_structure(self, lesson_plan_id: str) -> LessonPlanResponse:
        """Get the lesson plan structure."""
        validate_non_empty_string(lesson_plan_id, "lesson_plan_id")
        body = await self._transport.get(
            f"{self._base_path}/lessonPlans/tree/{quote(lesson_plan_id, safe='')}/structure"
        )
        return LessonPlanResponse.model_validate(body)

    async def update_student_item_response(
        self, input: LessonPlanUpdateStudentItemResponseInput | dict[str, Any]
    ) -> UpdateStudentItemResponseResult:
        """Update a student item response."""
        validate_with_schema(
            LessonPlanUpdateStudentItemResponseInput,
            input,
            "lesson plan update student item response",
        )
        body = await self._transport.post(
            f"{self._base_path}/lessonPlans/updateStudentItemResponse",
            serialize_input(input, LessonPlanUpdateStudentItemResponseInput),
        )
        return UpdateStudentItemResponseResult.model_validate(body)
