from datetime import datetime, timezone

from core.config import get_db
from core.security.exceptions import CoreDBError, GenericError
from models import Term, Course
from schema.term import TermResponseSchema


class TermService:

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

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

    def term_detail(self, term_id: int):
        with get_db() as db:
            record = db.query(Term).where(
                Term.id == term_id,
                Term.deleted_at.is_(None)
            ).first()

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

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

    def delete_term(self, term_id):

        with get_db() as db:
            if db.query(Course).where(Course.term_id == term_id).count() > 0:
                raise GenericError(status_code=422, exc="Age group is associated with course. Cannot delete.")
            term = db.query(Term).where(
                Term.id == term_id,
                Term.deleted_at.is_(None)
            ).first()

            if not term:
                raise GenericError(status_code=404, exc="Term not found")

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