from sqlalchemy.ext.asyncio import AsyncSession
from fastapi import APIRouter, HTTPException, Depends, status, Request, Query
from src.repo.task.TaskRepo import TaskRepo
from src.request.task.TaskRequest import TaskCreateRequest, TaskUpdateRequest, TaskResponse, ProjectModelMemeberTaskResponse
from typing import List, Optional
from src.util.jw import verify_jwt
from src.repo.engine import get_db

class TaskRouter:
    def __init__(self, repo: TaskRepo = Depends(TaskRepo)):
     
        self.router = APIRouter(prefix="/task", dependencies=[Depends(verify_jwt)])
        
        self.router.add_api_route("/get_task_status_generic", self.get_task_status_generic, methods=["GET"])
        self.router.add_api_route("/get_task_counts", self.get_task_counts, methods=["GET"])
        self.router.add_api_route("/get_user_wise_task_counts", self.get_user_wise_task_counts, methods=["GET"])
        self.router.add_api_route("/get_project_wise_task_counts", self.get_project_wise_task_counts, methods=["GET"])                
        self.router.add_api_route("/task_list_by_project", self.task_list_by_project, methods=["GET"], response_model=ProjectModelMemeberTaskResponse)
        self.router.add_api_route("/", self.index, methods=["GET"], response_model=List[TaskResponse])
        self.router.add_api_route("/", self.create, methods=["POST"], response_model=TaskResponse)
        self.router.add_api_route("/{id}", self.find, methods=["GET"], response_model=TaskResponse)
        self.router.add_api_route("/{id}", self.update, methods=["PUT"], response_model=TaskResponse)
       
    async def index(self, db:AsyncSession=Depends(get_db)):
        repo = TaskRepo(db)
        records = await repo.readAll()        
        return records

    async def create(self, data: TaskCreateRequest, request:Request, db:AsyncSession=Depends(get_db)):       
        try:
        # Pass the entire request object to the repository
        # and let the repository handle the business logic
            #records = self.repo.create(task_data=request)
            user_id = int(request.state.decoded_token.get("sub"))
            repo = TaskRepo(db)
            records = await repo.create(
                        data,
                        user_id
                        )
            return records
        except Exception as e:
            raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"An error occurred during task creation: {e}"
            )

    async def find(self, id: int, db:AsyncSession=Depends(get_db)):
        crud=TaskRepo(db)
        record = await crud.find(id)
        if record is not None:
            return record
        raise HTTPException(422, f" Record not found for id {id}")

    async def update(self, id: int, update_data: TaskUpdateRequest, request:Request,db:AsyncSession=Depends(get_db)):       
        try:
            user_id = int(request.state.decoded_token.get("sub"))
            crud = TaskRepo(db)
            #record = self.repo.find(id)
            db_project=await crud.update(id,update_data,user_id)
            if not db_project:
                 raise HTTPException(status_code=404,detail="Task Not Found")
            return db_project
            # if record is not None:            
            #     update_data = request.dict(exclude_unset=True)
            #     return self.repo.update(record=record, id=id, update_data=update_data)            
        except HTTPException as e:
            raise e
        except Exception as e:
            raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"An error occurred during task update: {e}"
            )

    async def task_list_by_project(self, project_id: int, db:AsyncSession=Depends(get_db)):
        repo=TaskRepo(db)
        record = await repo.task_list_by_project(project_id)
        if record is not None:
            return record
        raise HTTPException(422, f" Record not found for id {project_id}")
    
    async def get_task_counts(self, db:AsyncSession=Depends(get_db)):
        repo = TaskRepo(db)
        records = await repo.get_task_counts()        
        return records
    
    async def get_user_wise_task_counts(self, db:AsyncSession=Depends(get_db)):
        repo = TaskRepo(db)
        records = await repo.get_user_wise_task_counts()        
        return records
    
    async def get_project_wise_task_counts(self, db:AsyncSession=Depends(get_db)):
        repo = TaskRepo(db)
        records = await repo.get_project_wise_task_counts()        
        return records
    
    async def get_task_status_generic(self,  project_id: Optional[int] = Query(None, description="Filter by project ID"),
        user_id: Optional[int] = Query(None, description="Filter by user ID"),
        task_status: Optional[str] = Query(None, description="Filter by task status"), db:AsyncSession=Depends(get_db)):
        repo = TaskRepo(db)
        records = await repo.task_status_generic(project_id=project_id,
        user_id=user_id,
        task_status=task_status)        
        return records