"""Tool de exploracao — mapa do investigador para processos judiciais."""

import asyncio
import time
from typing import Any

from fastmcp import Context, FastMCP

from services.supabase_client import get_supabase_client
from services.usage_logger import get_usage_logger, ms_since
from tools._helpers import (
    MAX_PROCESSOS,
    MSG_PROCESSO_NAO_ENCONTRADO,
    _get_current_user,
    erro_instrutivo,
    paginar_resultado,
)


def register_explorar_tools(mcp: FastMCP) -> None:
    """Registra tools de exploracao no servidor MCP."""

    @mcp.tool
    async def explorar_processo(
        numero_processo: str | None = None,
        busca: str | None = None,
        limite: int = 20,
        offset: int = 0,
        ctx: Context = None,
    ) -> dict[str, Any]:
        """
        Mapa completo do processo — use SEMPRE como primeiro passo antes de qualquer analise.

        QUANDO usar:
        - Inicio de qualquer investigacao sobre um processo
        - Para descobrir quais documentos existem (catalogo com IDs)
        - Para entender a estrutura do processo antes de consultar/analisar

        FORMATOS de uso:
        1. explorar_processo(numero_processo="0000000-00.0000.0.00.0000") → Mapa completo
        2. explorar_processo(busca="nome da parte") → Busca por parte
        3. explorar_processo() → Lista processos disponiveis

        RETORNO (mapa completo):
        - dados_basicos: numero, classe, tribunal, instancia, valor, data
        - partes: lista com nome e tipo
        - catalogo_documentos: lista com {id, nome, tipo, tamanho_chars, data} para CADA doc
        - tipos_documentos: contagem por tipo
        - tipos_movimentacoes: contagem por tipo
        - estatisticas: total_documentos, total_movimentacoes, tamanho_total_mb
        - tipo_processo: "civel" ou "criminal"

        EXEMPLO:
        >>> mapa = explorar_processo("1234567-89.2024.8.26.0100")
        >>> # Depois use os IDs do catalogo:
        >>> consultar_documentos(document_id=mapa["catalogo_documentos"][0]["id"])

        Args:
            numero_processo: Numero CNJ (NNNNNNN-DD.AAAA.J.TR.OOOO). Se omitido, lista processos.
            busca: Nome da parte para buscar. Ignorado se numero_processo fornecido.
            limite: Maximo de resultados para listagem (default 20, max 50).
            offset: Offset para paginacao.
        """
        _start = time.perf_counter()
        user_id, user_email = _get_current_user()
        client = get_supabase_client()
        limite = min(limite, MAX_PROCESSOS)

        # --- Caminho 1: Mapa completo de um processo ---
        if numero_processo:
            # Chamadas paralelas para performance
            (
                processo,
                stats,
                metadados_docs,
                tipos_docs,
                tipos_movs,
                tipo_processo,
            ) = await asyncio.gather(
                client.processo_completo(numero_processo),
                client.stats_processo(numero_processo),
                client.listar_metadados_documentos(numero_processo),
                client.tipos_documentos_agregados(numero_processo),
                client.tipos_movimentacoes_agregados(numero_processo),
                client.detectar_tipo_processo(numero_processo),
            )

            if not processo:
                try:
                    get_usage_logger().log_tool_call(
                        tool_name="explorar_processo",
                        duration_ms=ms_since(_start),
                        success=False,
                        error_message="not_found",
                        user_id=user_id,
                        user_email=user_email,
                        params={"numero_processo": numero_processo},
                    )
                except Exception:
                    pass
                return erro_instrutivo(
                    f"Processo {numero_processo} nao encontrado.",
                    MSG_PROCESSO_NAO_ENCONTRADO,
                )

            # Formata dados basicos
            dados_basicos = {
                "numero_processo": processo.get("numero_processo"),
                "classe": processo.get("classe_descricao"),
                "tribunal": processo.get("sigla_tribunal"),
                "instancia": processo.get("instancia"),
                "valor_causa": processo.get("valor_causa"),
                "data_ajuizamento": processo.get("data_ajuizamento"),
            }

            # Formata partes
            partes_raw = processo.get("partes") or []
            partes = [{"nome": p.get("nome"), "tipo": p.get("tipo")} for p in partes_raw]

            # Formata catalogo de documentos (com IDs para uso posterior)
            catalogo_documentos = [
                {
                    "id": d.get("id"),
                    "nome": d.get("nome") or "Documento",
                    "tipo": d.get("tipo_nome"),
                    "tamanho_chars": d.get("tamanho_texto") or 0,
                    "data": str(d.get("data_juntada"))[:10] if d.get("data_juntada") else None,
                }
                for d in metadados_docs
            ]

            # Formata estatisticas
            estatisticas = {
                "total_documentos": stats.get("docs_extraidos", 0)
                if stats
                else len(metadados_docs),
                "total_movimentacoes": stats.get("movs_sincronizados", 0) if stats else 0,
                "tamanho_total_mb": round(
                    (stats.get("tamanho_total_bytes", 0) or 0) / 1024 / 1024, 2
                )
                if stats
                else 0,
            }

            try:
                get_usage_logger().log_tool_call(
                    tool_name="explorar_processo",
                    duration_ms=ms_since(_start),
                    user_id=user_id,
                    user_email=user_email,
                    params={"numero_processo": numero_processo},
                )
            except Exception:
                pass

            return {
                "sucesso": True,
                "dados_basicos": dados_basicos,
                "partes": partes,
                "catalogo_documentos": catalogo_documentos,
                "tipos_documentos": tipos_docs,
                "tipos_movimentacoes": tipos_movs,
                "estatisticas": estatisticas,
                "tipo_processo": tipo_processo,
            }

        # --- Caminho 2: Busca por parte ---
        if busca:
            resultados = await client.buscar_por_parte(busca)

            if not resultados:
                try:
                    get_usage_logger().log_tool_call(
                        tool_name="explorar_processo",
                        duration_ms=ms_since(_start),
                        success=False,
                        error_message="not_found",
                        user_id=user_id,
                        user_email=user_email,
                        params={"busca": busca},
                    )
                except Exception:
                    pass
                return erro_instrutivo(
                    f"Nenhum processo encontrado para parte '{busca}'.",
                    "Tente variar o nome (ex: sobrenome apenas) ou use explorar_processo() para listar todos.",
                )

            items = [
                {
                    "numero_processo": r.get("numero_processo"),
                    "classe": r.get("classe_descricao"),
                    "tribunal": r.get("sigla_tribunal"),
                    "valor_causa": r.get("valor_causa"),
                }
                for r in resultados[offset : offset + limite]
            ]

            try:
                get_usage_logger().log_tool_call(
                    tool_name="explorar_processo",
                    duration_ms=ms_since(_start),
                    user_id=user_id,
                    user_email=user_email,
                    params={"busca": busca},
                )
            except Exception:
                pass

            return {
                "sucesso": True,
                **paginar_resultado(items, len(resultados), limite, offset),
            }

        # --- Caminho 3: Lista processos disponiveis ---
        processos = await client.listar_todos_processos(limite=MAX_PROCESSOS)

        if not processos:
            try:
                get_usage_logger().log_tool_call(
                    tool_name="explorar_processo",
                    duration_ms=ms_since(_start),
                    success=False,
                    error_message="empty",
                    user_id=user_id,
                    user_email=user_email,
                )
            except Exception:
                pass
            return erro_instrutivo(
                "Nenhum processo disponivel.",
                "Sincronize processos em " + "https://tecjusticamcp3.vercel.app/login",
            )

        items = []
        for job in processos[offset : offset + limite]:
            proc_raw = job.get("processos") or {}
            # PostgREST pode retornar lista (one-to-many) ou dict (many-to-one)
            proc = (
                proc_raw[0]
                if isinstance(proc_raw, list) and proc_raw
                else proc_raw
                if isinstance(proc_raw, dict)
                else {}
            )
            items.append(
                {
                    "numero_processo": proc.get("numero_processo") or job.get("numero_processo"),
                    "classe": proc.get("classe_descricao"),
                    "tribunal": proc.get("sigla_tribunal"),
                    "valor_causa": proc.get("valor_causa"),
                }
            )

        try:
            get_usage_logger().log_tool_call(
                tool_name="explorar_processo",
                duration_ms=ms_since(_start),
                user_id=user_id,
                user_email=user_email,
            )
        except Exception:
            pass

        return {
            "sucesso": True,
            **paginar_resultado(items, len(processos), limite, offset),
        }
