from typing import Any

from pydantic import BaseModel, Field
from pydantic_ai import Agent, RunContext

from app.agent.deps import Deps


class BoundingBox(BaseModel):
    left: float
    top: float
    right: float
    bottom: float


class ExtractedTable(BaseModel):
    cells: list[list[str]] = Field(default_factory=list)
    markdown: str = Field(default_factory=str)
    page_number: int = 0
    bounding_box: BoundingBox | None = None


class FileText(BaseModel):
    content: str = Field(default_factory=str)
    mime_type: str = Field(default_factory=str)
    tables: list[ExtractedTable] = Field(default_factory=list)

    @classmethod
    def from_extraction_result(cls, result: Any) -> "FileText":
        return cls(
            content=getattr(result, "content", ""),
            mime_type=getattr(result, "mime_type", ""),
            tables=getattr(result, "tables", []) or [],
        )


def configure_get_text_tool(
    agent: Agent[Deps, str],
) -> Agent[Deps, str]:
    @agent.tool
    async def get_text(ctx: RunContext[Deps], path: str) -> FileText:
        """Extrai o conteúdo textual de um arquivo do workspace.

        Suporta .pdf, .docx, .xlsx, .html e outros formatos com texto pesquisável.

        Args:
            path: Caminho para o arquivo, relativo ao workspace.
        """

        from kreuzberg import ExtractionConfig, PageConfig, extract_file

        file_path = ctx.deps.workspace_dir / path

        if not file_path.exists():
            return FileText(content=f"[ERRO] Arquivo não encontrado: {path}")

        try:
            result = await extract_file(
                file_path,
                config=ExtractionConfig(
                    output_format="plain",
                    ocr=None,
                    pages=PageConfig(
                        extract_pages=True,
                        insert_page_markers=True,
                        marker_format="\n\n<!-- PÁGINA {page_num} -->\n\n",
                    ),
                ),
            )
            return FileText.from_extraction_result(result)
        except Exception as e:
            return FileText(content=f"[ERRO]: {type(e).__name__} | {str(e)}")

    return agent
