from typing import Literal
from fastapi import HTTPException
from pydantic import Field
from sqlalchemy import INTEGER,VARCHAR, Enum, ForeignKey, text
from app.models.main import Base
from app.utils.schemas_utils import CustomModel
from sqlalchemy.orm import (Mapped,Session,mapped_column,relationship)

class StudentBase(CustomModel):
    
    student_id: int | None = Field(default=None)
    first_name: str | None = Field(default=None)
    last_name: str | None = Field(default=None)
    student_email: str | None = Field(default=None)
    password: str | None = Field(default=None)
    role: Literal["student"] = Field(default="student") 
    roll_no :  int | None = Field(default=None)
    group_code:str | None = Field(default=None)
    

class StudentFilter(CustomModel):
    student_id: int | None = Field(default=None) 
    student_email: str | None = Field(default=None)     

class TblStudent(Base):
    __tablename__ = "tbl_student"

    student_id: Mapped[int] = mapped_column("student_id", INTEGER, primary_key=True, autoincrement=True)
    first_name: Mapped[str] = mapped_column("first_name", VARCHAR(255), nullable=True)
    last_name: Mapped[str] = mapped_column("last_name", VARCHAR(255), nullable=True)
    student_email: Mapped[str] = mapped_column("student_email", VARCHAR(255), nullable=True)
    password: Mapped[str] = mapped_column("password", VARCHAR(255), nullable=False)
    role: Mapped[str] = mapped_column("role", VARCHAR(50), nullable=False, default="student")
    roll_no : Mapped[int] = mapped_column("roll_no", INTEGER, nullable=True, server_default=None)
    group_code: Mapped[str] = mapped_column("group_code", VARCHAR(100), ForeignKey("tbl_group.group_code"), nullable=True)
    login_status: Mapped[str] = mapped_column("login_status", Enum("0", "1"), nullable=True, server_default=text("1"))

    group = relationship("TblGroup", back_populates="students")

    @classmethod
    def create(cls, data: StudentBase, db: Session) -> "TblStudent":
        data_dict = data.model_dump()
        new_data = cls(**data_dict)
        db.add(new_data)
        db.flush()
        return new_data

    @classmethod
    def get_by_student_email(cls, student_email: int, db: Session) -> "TblStudent":
        get_data = db.query(cls).filter(cls.student_email == student_email).first()
        if not get_data:
            raise HTTPException(status_code=404, detail="User not found") 
        return get_data 
    
    @classmethod
    def get_by_id(cls, student_id: int, db: Session) -> "TblStudent":  
        get_data = db.query(cls).filter(cls.student_id == student_id).first()
        if not get_data:
            raise HTTPException(status_code=404, detail="Student not found") 
        return get_data
    
    @classmethod
    def update(cls,  student_id : int, data: StudentBase, db: Session) -> "TblStudent":
        get_data = db.query(cls).filter(cls. student_id ==  student_id ).first()
        if not get_data:
            raise HTTPException(status_code=404, detail="Store format not found") 
        data_dict = data.model_dump()
        for key, value in data_dict.items():
            if value is not None:
                setattr(get_data, key, value)
        db.commit() 
        db.refresh(get_data)  
        return get_data
    
    @classmethod
    def get_by_user_filter(cls, request: dict | StudentFilter, db: Session) -> StudentBase | None:
        if isinstance(request, dict):
            filter_data = request
        else:
            filter_data = request.model_dump(exclude_none=True)
        get_user_data = db.query(cls).filter_by(**filter_data).first()
        if not get_user_data:
            return None
        return StudentBase(**get_user_data.__dict__)


