import uuid
from datetime import datetime, timezone
from pathlib import Path

from sqlalchemy.orm import joinedload
from sqlalchemy import or_, update
from core.config import get_db, BASE_PATH
from core.security.exceptions import GenericError
from models import Course, AgeGroup
from schema.course import CourseResponseSchema


class CourseService:

    async def upload_image(self, request):
        if request.image:
            file_extension = Path(request.image.filename).suffix
            new_filename = f"{uuid.uuid4()}{file_extension}"
            file_location = BASE_PATH / f'uploads/{new_filename}'
            content = await request.image.read()
            with open(file_location, "wb") as f:
                f.write(content)
            return new_filename
        return None

    async def add_new_course(self, request):
        payload = request.model_dump(exclude=['image','remaining_seat'])
        image = await self.upload_image(request)
        if image:
            payload['image'] = image
        with get_db() as db:
            new_course = Course(**payload)
            db.add(new_course)
            db.commit()
            db.refresh(new_course)
            return new_course

    def fetch_all_course(self, date):
        with get_db() as db:
            query = db.query(Course).options(joinedload(Course.academic_year), joinedload(Course.term),
                                             joinedload(Course.course_category),
                                             joinedload(Course.age_group),
                                             joinedload(Course.time_slot)).where(
                Course.deleted_at.is_(None))
            if date == "present":
                query = query.filter(Course.end_date >= datetime.today())

            records = query.all()
            print(records)
            return [CourseResponseSchema.model_validate(record).model_dump() for record in records]

    def fetch_course_details(self, course_id: int):
        with get_db() as db:
            record = db.query(Course).options(joinedload(Course.academic_year), joinedload(Course.term),
                                              joinedload(Course.course_category)).where(
                Course.id == course_id,
                Course.deleted_at.is_(None)
            ).first()

            if not record:
                raise GenericError(status_code=404, exc="Course not found")
            return CourseResponseSchema.model_validate(record).model_dump()

    async def update_course(self, course_id, request):
        payload = request.model_dump(exclude=['id', 'image','remaining_seat'])
        image = await self.upload_image(request)
        if image:
            payload['image'] = image

        with get_db() as db:
            result = (db.query(Course).where(Course.id == course_id, Course.deleted_at.is_(None)).update(payload,
                                                                                                         synchronize_session="fetch"))
            db.commit()
            if result == 0:
                raise GenericError(status_code=422, exc="Could not update course")

    def delete_course(self, course_id):
        with get_db() as db:
            course = db.query(Course).where(Course.id == course_id, Course.deleted_at.is_(None)).first()

            if not course:
                raise GenericError(status_code=404, exc="Course not found")

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

    def fetch_age_swapping_record(self,age_group_id):
        with get_db() as db:
            age_instance=db.query(AgeGroup).where(AgeGroup.id==age_group_id).first()
            values = list(range(age_instance.age_start, age_instance.age_end + 1))
            all_age_groups=db.query(AgeGroup).filter(
                or_(
                    AgeGroup.age_start.in_(values),
                    AgeGroup.age_end.in_(values)
                )

            ).all()
            return [row.id for row in all_age_groups]

    def course_filter(self, request):
        with get_db() as db:

            query = db.query(Course).options(joinedload(Course.academic_year), joinedload(Course.term),
                                             joinedload(Course.course_category)).filter(
                Course.deleted_at.is_(None))
            if request.age_group_id:
                #self.fetch_age_swapping_record(request.age_group_id))
                query = query.filter(Course.age_group_id.in_(request.age_group_id))
            if request.course_category_id:
                query = query.filter(Course.course_category_id == request.course_category_id)
            if request.time_slot_id:
                query = query.filter(Course.time_slot_id == request.time_slot_id)
            if request.date == "present":
                query = query.filter(Course.end_date >= datetime.today())
            if request.academic_year_id:
                query = query.filter(Course.academic_year_id == request.academic_year_id)
            if request.term_id:
                query = query.filter(Course.term_id == request.term_id)
            if request.is_active:
                query=query.filter(Course.is_active==request.is_active)
            if request.is_special_course is not None:
                query = query.filter(Course.is_special_course == request.is_special_course)

            records = query.all()
            return [CourseResponseSchema.model_validate(record).model_dump() for record in records]

    def toogle_enable(self, course_id):
        with get_db() as db:
            db.execute(
                update(Course)
                .where(Course.id == course_id)
                .values(is_active=~Course.is_active)
            )

            db.commit()


