import uuid
from typing import Annotated
from fastapi import Depends
from sqlmodel import select
from sqlmodel.ext.asyncio.session import AsyncSession

from maur.models import CodingTask, SessionDep


class DuplicateTaskError(Exception):
    def __init__(self, existing_task_id: uuid.UUID) -> None:
        self.existing_task_id = existing_task_id
        super().__init__(f"Task with source_id already in progress: {existing_task_id}")


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

    async def insert(self, task: CodingTask) -> CodingTask:
        existing = await self._find_in_progress(task.source_id)
        if existing:
            raise DuplicateTaskError(existing.id)
        return await task.insert(self.session)

    async def _find_in_progress(self, source_id: str) -> CodingTask | None:
        result = await self.session.exec(
            select(CodingTask)
            .where(CodingTask.source_id == source_id)
            .where(CodingTask.finnished_at == None)  # type: ignore[union-attr]
            .where(CodingTask.error == None)  # type: ignore[union-attr]
        )
        return result.first()


def coding_task_repo(session: SessionDep) -> CodingTaskRepo:
    return CodingTaskRepo(session)


CodingTaskRepoDep = Annotated[CodingTaskRepo, Depends(coding_task_repo)]
