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

from core.config import get_db, BASE_PATH
from core.security.exceptions import GenericError
from models import CourseCategory, Course
from schema.course_category import CourseCategoryResponseSchema


class CourseCategoryService:

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

    async def create_course_category(self, request):
        payload = request.model_dump(exclude=['icon'])
        icon = await self.upload_image(request)
        if icon:
            payload['icon'] = icon

        with get_db() as db:
            new_course_category = CourseCategory(**payload)
            db.add(new_course_category)
            db.commit()
            db.refresh(new_course_category)
            return new_course_category

    def fetch_all_course_category(self):
        with get_db() as db:
            records = db.query(CourseCategory).where(CourseCategory.deleted_at.is_(None)).all()
            return [CourseCategoryResponseSchema.model_validate(record).model_dump() for record in records]

    def fetch_course_category_details(self, course_category_id: int):
        with get_db() as db:
            record = db.query(CourseCategory).where(CourseCategory.id == course_category_id,
                                                    CourseCategory.deleted_at.is_(None)).first()

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

    async def update_course_category(self, course_category_id, request):
        payload = request.model_dump(exclude=['id', 'icon'])
        icon = await self.upload_image(request)
        if icon:
            payload['icon'] = icon

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

    def delete_course_category(self, course_category_id):
        with get_db() as db:
            if db.query(Course).where(Course.course_category_id == course_category_id).count() > 0:
                raise GenericError(status_code=422, exc="Course category is associated with course. Cannot delete.")
            course_category = db.query(CourseCategory).where(CourseCategory.id == course_category_id,
                                                             CourseCategory.deleted_at.is_(None)).first()

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

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