from sqlalchemy.ext.asyncio import AsyncSession
from src.models.module.models import Module
from src.models.project.models import Project
from sqlalchemy import select
from datetime import datetime,timezone
from src.request.module.ModuleRequest import ModuleCreateRequest, ModuleUpdateRequest, ModuleWithProject, ModuleDDLReponse

class ModuleRepo:
    def __init__(self,session:AsyncSession) -> None:
        self.session = session

    async def create(self, module:ModuleCreateRequest, user_id: int) -> Module:
        record=Module(**module.model_dump())
        record.created_by = user_id
        self.session.add(record)
        await self.session.commit()
        await self.session.refresh(record)
        return record

    async def update(self, id: int, update_data: ModuleUpdateRequest, user_id:int) -> Module:                       
        db_state=await self.find(id)
        if not db_state:
            return None
        for key,value in update_data.model_dump(exclude_unset=True).items():
            setattr(db_state,key,value)

        db_state.updated_at = datetime.now(timezone.utc)
        db_state.updated_by = user_id
        await self.session.commit()
        await self.session.refresh(db_state)
        return db_state
    
    async def find(self, id: int) -> Module | None:
        result=await self.session.execute(select(Module).where(Module.id==id))
        return result.scalar_one_or_none()
    
    async def readAll(self) -> list[Module]:
        result = await self.session.execute(select(Module))
        return result.scalars().all()
                
    async def get_modules_by_project(self, project_id: int) -> list[ModuleWithProject]:
        stmt = (
            select(
                Module.id.label("module_id"),
                Module.title.label("module_title"),
                Module.description.label("module_description"),
                Module.is_active,
                Project.id.label("project_id"),
                Project.name.label("project_name"),
            )
            .join(Project, Project.id == Module.project_id)
            .where(Project.id == project_id)
        )

        result = await self.session.execute(stmt)
        rows = result.all()

        return [ModuleWithProject(**row._asdict()) for row in rows]    
    
    async def get_module_ddl(self, project_id: int) -> list[ModuleDDLReponse]:
        stmt = (
            select(
                Module.id.label("id"),
                Module.title.label("name"),
                )
            .join(Project, Project.id == Module.project_id)
            .where(Project.id == project_id)
        )
        result = await self.session.execute(stmt)
        rows = result.all()

        return [ModuleDDLReponse(**row._asdict()) for row in rows]    
      