from datetime import datetime, timezone

from schema.teacher_course import TeacherCourseResponseSchema
from sqlalchemy.orm import joinedload

from core.config import get_db
from core.security.exceptions import GenericError
from models import TeacherCourse


class TeacherCourseService:

    def create_new_teacher_course(self, request):
        payload = request.model_dump()
        with get_db() as db:
            new_teacher_course = TeacherCourse(**payload)
            db.add(new_teacher_course)
            db.commit()
            db.refresh(new_teacher_course)
            return new_teacher_course

    def fetch_all_teacher_course(self):
        with get_db() as db:
            records = db.query(TeacherCourse).options(joinedload(TeacherCourse.teacher),
                                                      joinedload(TeacherCourse.course)).where(
                TeacherCourse.deleted_at.is_(None)).all()
            return [TeacherCourseResponseSchema.model_validate(record).model_dump() for record in records]

    def fetch_teacher_course_details(self, teacher_course_id: int):
        with get_db() as db:
            record = db.query(TeacherCourse).where(
                TeacherCourse.id == teacher_course_id,
                TeacherCourse.deleted_at.is_(None)
            ).first()

            if not record:
                raise GenericError(status_code=404, exc="Teacher course mapping not found")
            return TeacherCourseResponseSchema.model_validate(record).model_dump()

    def update_teacher_course(self, teacher_course_id, request):
        payload = request.model_dump(exclude=['id'])
        with get_db() as db:
            result = (
                db.query(TeacherCourse)
                .filter(TeacherCourse.id == teacher_course_id, TeacherCourse.deleted_at.is_(None))
                .update(payload, synchronize_session="fetch")
            )
            db.commit()
            if result == 0:
                raise GenericError(status_code=422, exc="Could not update teacher course mapping")

    def delete_teacher_course(self, teacher_course_id):
        with get_db() as db:
            teacher_course = db.query(TeacherCourse).where(
                TeacherCourse.id == teacher_course_id,
                TeacherCourse.deleted_at.is_(None)
            ).first()

            if not teacher_course:
                raise GenericError(status_code=404, exc="Teacher course mapping not found")

            teacher_course.deleted_at = datetime.now(timezone.utc)
            db.commit()
            return {"message": "Teacher course mapping deleted successfully"}
