from datetime import datetime, timezone

from core.config import get_db
from core.security.exceptions import CoreDBError, GenericError
from models import AcademicYear, Course
from schema.academic_year import AcademicYearResponseSchema


class AcademicYearService:

    def save(self, request):
        with get_db() as db:
            payload = request.model_dump()
            try:
                new_academic_year = AcademicYear(**payload)
                db.add(new_academic_year)
                db.commit()
                db.refresh(new_academic_year)
                return new_academic_year
            except Exception as e:
                db.rollback()
                raise CoreDBError(f"Could not create new academic year: {e}")

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

    def academic_year_detail(self, academic_year_id: int):
        with get_db() as db:
            record = db.query(AcademicYear).where(
                AcademicYear.id == academic_year_id,
                AcademicYear.deleted_at.is_(None)
            ).first()

            if not record:
                raise GenericError(status_code=404, exc="Academic year not found")
            return AcademicYearResponseSchema.model_validate(record).model_dump()

    def update_academic_year(self, academic_year_id, request):
        payload = request.model_dump(exclude=['id'])
        with get_db() as db:
            result = (
                db.query(AcademicYear)
                .filter(AcademicYear.id == academic_year_id, AcademicYear.deleted_at.is_(None))
                .update(payload, synchronize_session="fetch")
            )
            db.commit()
            if result == 0:
                raise GenericError(status_code=422, exc="Could not update academic year")

    def delete_academic_year(self, academic_year_id):
        with get_db() as db:
            if db.query(Course).where(Course.academic_year_id == academic_year_id).count() > 0:
                raise GenericError(status_code=422, exc="Academic year is associated with course. Cannot delete.")
            academic_year = db.query(AcademicYear).where(
                AcademicYear.id == academic_year_id,
                AcademicYear.deleted_at.is_(None)
            ).first()

            if not academic_year:
                raise GenericError(status_code=404, exc="Academic year not found")

            academic_year.deleted_at = datetime.now(timezone.utc)
            db.commit()
            return {"message": "Academic year deleted successfully"}
