"""
TecJustica MCP Server

MCP Server para consulta de processos judiciais armazenados no Supabase.
Usa FastMCP com autenticacao via Supabase Auth (DCR) e OpenRouter para queries LLM.
"""

import base64
import hashlib
import logging
import os

from fastmcp import FastMCP
from fastmcp.server.auth import AccessToken, TokenVerifier
from fastmcp.server.auth.providers.jwt import JWTVerifier
from fastmcp.server.auth.providers.supabase import SupabaseProvider
from mcp.types import Icon

from tools import (
    register_analise_tools,
    register_busca_tools,
    register_estatisticas_tools,
    register_navegacao_tools,
    register_precedentes_tools,
    register_user_tools,
    register_utilidades_tools,
)

# Configuracao de logging
logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
)
logger = logging.getLogger("tecjustica-mcp")

# Icone SVG da balanca da justica (TecJustica)
# Design minimalista: balanca equilibrada com base solida
TECJUSTICA_ICON_SVG = """<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" fill="none">
  <!-- Base e pilar central -->
  <rect x="28" y="52" width="8" height="8" rx="1" fill="#1e3a5f"/>
  <rect x="20" y="58" width="24" height="4" rx="1" fill="#1e3a5f"/>
  <rect x="30" y="16" width="4" height="36" fill="#1e3a5f"/>

  <!-- Traves horizontais -->
  <rect x="8" y="14" width="48" height="4" rx="2" fill="#2563eb"/>

  <!-- Prato esquerdo -->
  <path d="M8 22 L8 18 L12 18 L12 22 L8 22" fill="#1e3a5f"/>
  <path d="M4 32 Q10 28 16 32 L14 38 Q10 40 6 38 Z" fill="#2563eb"/>
  <line x1="10" y1="22" x2="10" y2="28" stroke="#1e3a5f" stroke-width="2"/>

  <!-- Prato direito -->
  <path d="M52 22 L52 18 L56 18 L56 22 L52 22" fill="#1e3a5f"/>
  <path d="M48 32 Q54 28 60 32 L58 38 Q54 40 50 38 Z" fill="#2563eb"/>
  <line x1="54" y1="22" x2="54" y2="28" stroke="#1e3a5f" stroke-width="2"/>

  <!-- Circulo central (simbolo de equilibrio) -->
  <circle cx="32" cy="12" r="6" fill="#2563eb"/>
  <circle cx="32" cy="12" r="3" fill="#ffffff"/>
</svg>"""


def _get_server_icon() -> Icon:
    """
    Retorna o icone do servidor TecJustica como data URI.

    Returns:
        Icon configurado com SVG em base64
    """
    svg_bytes = TECJUSTICA_ICON_SVG.strip().encode("utf-8")
    svg_base64 = base64.b64encode(svg_bytes).decode("utf-8")
    data_uri = f"data:image/svg+xml;base64,{svg_base64}"

    return Icon(
        src=data_uri,
        mimeType="image/svg+xml",
        sizes=["64x64"],
    )


class DualTokenVerifier(TokenVerifier):
    """Valida tokens tk_ via hash em env var, ou delega JWT ao JWTVerifier."""

    def __init__(self, jwt_verifier: JWTVerifier) -> None:
        super().__init__()
        self.jwt_verifier = jwt_verifier
        self.api_keys: dict[str, dict[str, str]] = {}
        self._load_api_keys()

    def _load_api_keys(self) -> None:
        """Carrega API keys de env var API_KEY_HASHES.

        Formato: sha256hash:user_id:email[,sha256hash2:user_id2:email2]
        """
        raw = os.getenv("API_KEY_HASHES", "")
        for entry in raw.split(","):
            entry = entry.strip()
            if not entry:
                continue
            parts = entry.split(":")
            if len(parts) == 3:
                token_hash, user_id, email = parts
                self.api_keys[token_hash] = {"user_id": user_id, "email": email}
        if self.api_keys:
            logger.info("Carregadas %d API keys fixas", len(self.api_keys))

    async def verify_token(self, token: str) -> AccessToken | None:
        if token.startswith("tk_"):
            token_hash = hashlib.sha256(token.encode()).hexdigest()
            key_data = self.api_keys.get(token_hash)
            if not key_data:
                return None
            return AccessToken(
                token=token,
                client_id=key_data["user_id"],
                scopes=[],
                expires_at=None,
                claims={"sub": key_data["user_id"], "email": key_data["email"]},
            )
        return await self.jwt_verifier.verify_token(token)


def create_mcp_server() -> FastMCP:
    """
    Cria e configura o servidor MCP.

    Usa SupabaseProvider com DCR (Dynamic Client Registration).
    O Supabase OAuth Server gerencia o registro automatico de clientes MCP.

    Returns:
        Instancia configurada do FastMCP
    """
    # Verifica configuracao de autenticacao
    auth_enabled = os.getenv("AUTH_ENABLED", "true").lower() == "true"
    supabase_url = os.getenv("SUPABASE_URL", "").rstrip("/")
    base_url = os.getenv("MCP_BASE_URL", "http://localhost:8000")

    # Obtem icone do servidor
    server_icon = _get_server_icon()

    # Cria servidor com ou sem auth
    if auth_enabled and supabase_url:
        logger.info("Autenticacao habilitada via Supabase DCR")
        logger.info("Supabase URL: %s", supabase_url)
        logger.info("MCP Base URL: %s", base_url)

        # SupabaseProvider usa DCR - clientes MCP se registram automaticamente
        # DualTokenVerifier: tokens tk_ via hash SHA-256, JWTs via JWKS
        jwt_verifier = JWTVerifier(
            jwks_uri=f"{supabase_url}/auth/v1/.well-known/jwks.json",
            issuer=f"{supabase_url}/auth/v1",
            algorithm="ES256",
        )
        dual_verifier = DualTokenVerifier(jwt_verifier)
        auth = SupabaseProvider(
            project_url=supabase_url,
            base_url=base_url,
            token_verifier=dual_verifier,
        )

        mcp = FastMCP(
            name="TecJustica MCP Server",
            version="4.0.0",
            auth=auth,
            icons=[server_icon],
        )
    else:
        logger.warning("Autenticacao DESABILITADA - apenas para desenvolvimento!")
        mcp = FastMCP(
            name="TecJustica MCP Server",
            version="4.0.0",
            icons=[server_icon],
        )

    # Registra todos os tools
    logger.info("Registrando tools...")
    register_navegacao_tools(mcp)
    register_busca_tools(mcp)
    register_estatisticas_tools(mcp)
    register_analise_tools(mcp)
    register_user_tools(mcp)
    register_precedentes_tools(mcp)
    register_utilidades_tools(mcp)

    logger.info("Servidor MCP configurado com sucesso")
    return mcp


# Cria instancia global do servidor
mcp = create_mcp_server()


# ==================== RESOURCES ====================


@mcp.resource("processo://{numero_processo}")
async def get_processo_resource(numero_processo: str) -> str:
    """
    Resource para acesso a dados de um processo.

    URI: processo://NNNNNNN-DD.AAAA.J.TR.OOOO
    """
    from services.supabase_client import get_supabase_client

    client = get_supabase_client()
    processo = await client.processo_completo(numero_processo)

    if not processo:
        return f"Processo {numero_processo} nao encontrado"

    return client._formatar_processo(processo)


@mcp.resource("documento://{document_id}")
async def get_documento_resource(document_id: str) -> str:
    """
    Resource para acesso ao conteudo de um documento.

    URI: documento://<uuid>
    """
    from services.supabase_client import get_supabase_client

    client = get_supabase_client()
    doc = await client.ler_documento(document_id)

    if not doc:
        return f"Documento {document_id} nao encontrado"

    return client._formatar_documento(doc)


# ==================== PROMPTS PROFISSIONAIS ====================


@mcp.prompt
def analise_completa(numero_processo: str) -> str:
    """
    Prompt para analise juridica profissional completa.

    Guia uma analise sistematica como advogado experiente faria.

    Args:
        numero_processo: Numero do processo a analisar
    """
    return f"""# ANALISE JURIDICA PROFISSIONAL - Processo {numero_processo}

Voce e um advogado senior realizando analise completa deste processo.

## FASE 0: EXPLORACAO (OBRIGATORIO)
1. `visao_geral_processo("{numero_processo}")` — Metadados, partes, stats de documentos, movimentacoes recentes
2. `stats_documentos("{numero_processo}")` — Panorama quantitativo dos documentos

## FASE 1: COLETA SELETIVA
Com base nos stats, escolha os documentos mais relevantes:
3. `grep_documentos("sentenca", numero_processo="{numero_processo}")` — Encontrar sentencas
4. `read_documento("<id-sentenca>")` — Ler sentenca/acordao
5. `read_documento("<id-peticao-inicial>")` — Ler peticao inicial
6. `ls_movimentacoes("{numero_processo}")` — Timeline completa

## FASE 2: ANALISE
7. `analisar("{numero_processo}", "Qual a situacao atual? Fase, pendencias, alertas.")`
8. `analisar("{numero_processo}", "Extraia todos os pedidos com tipo, valor e status.")`
9. `analisar("{numero_processo}", "Analise as decisoes: fundamentacao, ratio decidendi.")`

## FASE 3: AVALIACAO ESTRATEGICA
10. `analisar("{numero_processo}", "Analise de risco completa com cenarios.", perspectiva="autor")`
11. `analisar("{numero_processo}", "Analise de risco completa com cenarios.", perspectiva="reu")`

## FASE 4: CONCLUSAO
Elabore: sintese (5 linhas), pontos criticos, probabilidade de exito,
recomendacoes estrategicas, proximos passos processuais.

Inicie pela FASE 0."""


@mcp.prompt
def parecer_tecnico(numero_processo: str, questao: str) -> str:
    """
    Prompt para elaboracao de parecer juridico tecnico.

    Args:
        numero_processo: Numero do processo
        questao: Questao juridica especifica a responder
    """
    return f"""# PARECER JURIDICO TECNICO

**Processo:** {numero_processo}
**Questao Juridica:** {questao}

Voce e um parecerista juridico elaborando parecer tecnico formal.

## METODOLOGIA

1. `visao_geral_processo("{numero_processo}")` — Metadados, partes e stats
2. `grep_documentos("termo relevante", numero_processo="{numero_processo}")` — Buscar documentos chave
3. `analisar("{numero_processo}", "{questao}")` — Parecer base sobre a questao
4. `analisar("{numero_processo}", "Analise as decisoes e fundamentacao juridica.")` — Jurisprudencia
5. `analisar("{numero_processo}", "Argumentos de cada polo processual.")` — Ambos os lados

Estruture a resposta no formato:

## EMENTA
[3-5 linhas com a sintese e conclusao]

## I. RELATORIO
[Fatos relevantes e historico]

## II. FUNDAMENTACAO
[Analise juridica detalhada]

## III. CONCLUSAO
[Resposta objetiva a questao]

## IV. RECOMENDACOES
[Acoes sugeridas]

Cite artigos de lei, doutrina e jurisprudencia quando possivel.

Inicie a elaboracao do parecer."""


@mcp.prompt
def due_diligence(numero_processo: str) -> str:
    """
    Prompt para due diligence processual completa.

    Analise para tomada de decisao (acordo, aquisicao, etc).

    Args:
        numero_processo: Numero do processo
    """
    return f"""# DUE DILIGENCE PROCESSUAL - {numero_processo}

Voce esta realizando due diligence juridica para tomada de decisao empresarial.
Esta analise sera usada para avaliar riscos em negociacao de acordo ou M&A.

## ETAPA 1: EXPLORACAO
1. `visao_geral_processo("{numero_processo}")` — Metadados, partes, stats

## ETAPA 2: COLETA
2. `glob_documentos("{numero_processo}", padrao_tipo="Sentenca")` — Docs decisorios
3. `grep_documentos("pedido indenizacao", numero_processo="{numero_processo}")` — Buscar conteudo relevante
4. `ls_movimentacoes("{numero_processo}")` — Timeline

## ETAPA 3: ANALISE
5. `analisar("{numero_processo}", "Situacao atual, fase processual e pendencias.")`
6. `analisar("{numero_processo}", "Extraia pedidos e exposicao financeira total.")`
7. `analisar("{numero_processo}", "Analise de risco completa com cenarios.", perspectiva="reu")`

## ETAPA 4: VALORACAO

Com os dados, produza:

### FICHA TECNICA
| Item | Valor |
|------|-------|
| Classe | |
| Valor da Causa | R$ |
| Data Ajuizamento | |
| Fase Atual | |
| Instancia | |

### ANALISE DE CONTINGENCIA
**Classificacao de Risco:** [Provavel/Possivel/Remoto]
**Valor Provisionado Sugerido:** R$ [valor]
**Justificativa:** [Razoes para a classificacao]

### CENARIOS
| Cenario | Probabilidade | Impacto Financeiro |
|---------|---------------|-------------------|
| Melhor | X% | R$ |
| Provavel | X% | R$ |
| Pior | X% | R$ |

### RECOMENDACAO
[Acordo? Provisionar? Litigar? Valor sugerido de acordo]

Inicie pela ETAPA 1."""


@mcp.prompt
def preparar_audiencia(numero_processo: str, tipo_audiencia: str = "instrucao") -> str:
    """
    Prompt para preparacao de audiencia.

    Args:
        numero_processo: Numero do processo
        tipo_audiencia: conciliacao, instrucao, julgamento
    """
    return f"""# PREPARACAO PARA AUDIENCIA - {numero_processo}

**Tipo de Audiencia:** {tipo_audiencia.upper()}

Voce esta preparando advogado para audiencia. Analise o processo e prepare briefing.

## COLETA
1. `visao_geral_processo("{numero_processo}")` — Metadados, partes e stats
2. `glob_documentos("{numero_processo}", padrao_tipo="Sentenca")` — Docs decisorios
3. `grep_documentos("audiencia", numero_processo="{numero_processo}")` — Buscar audiencias
4. `ls_movimentacoes("{numero_processo}")` — Timeline

## ANALISE
5. `analisar("{numero_processo}", "Argumentos de cada polo processual.")`
6. `analisar("{numero_processo}", "Analise das decisoes ja proferidas.")`
7. `analisar("{numero_processo}", "Pontos controvertidos e questoes pendentes.")`

## BRIEFING

### 1. RESUMO DO CASO (1 pagina)
- Objeto, partes, pedidos, valor

### 2. PONTOS CONTROVERTIDOS
[O que sera discutido na audiencia]

### 3. ARGUMENTOS CHAVE
**Nossa Posicao** vs **Posicao Adversa**

### 4. PERGUNTAS PARA TESTEMUNHAS (se instrucao)

### 5. PROPOSTA DE ACORDO (se conciliacao)
- Valor minimo aceitavel: R$
- Valor ideal: R$

### 6. CHECKLIST PRE-AUDIENCIA

Prepare o briefing completo."""


@mcp.prompt
def estrategia_recursal(numero_processo: str) -> str:
    """
    Prompt para analise de estrategia recursal.

    Args:
        numero_processo: Numero do processo
    """
    return f"""# ANALISE DE ESTRATEGIA RECURSAL - {numero_processo}

Voce e advogado especialista em recursos avaliando se deve recorrer e como.

## COLETA
1. `visao_geral_processo("{numero_processo}")` — Metadados e stats
2. `glob_documentos("{numero_processo}", padrao_tipo="Sentenca")` — Decisoes
3. `grep_documentos("recurso apelacao", numero_processo="{numero_processo}")` — Buscar pecas recursais

## ANALISE
4. `analisar("{numero_processo}", "Analise detalhada da decisao recorrida: dispositivo, fundamentacao, pontos vulneraveis.")`
5. `analisar("{numero_processo}", "Analise de risco se recorrer vs nao recorrer.", perspectiva="autor")`

## RELATORIO RECURSAL

### 1. DECISAO RECORRIDA
- Tipo, Data, Dispositivo

### 2. RECURSOS CABIVEIS
| Recurso | Prazo | Cabimento | Chance de Exito |
|---------|-------|-----------|-----------------|
| Apelacao/Agravo/Embargos/REsp/RE |

### 3. ANALISE DE VIABILIDADE
- Questao de Fato vs Direito
- Prequestionamento
- Jurisprudencia Favoravel

### 4. TESES RECURSAIS SUGERIDAS

### 5. RECOMENDACAO
Recorrer / Nao recorrer / Parcialmente

### 6. CUSTO-BENEFICIO
- Custas, tempo, probabilidade de reforma

Execute a analise completa."""


@mcp.prompt
def guia_ferramentas() -> str:
    """Prompt com guia completo das ferramentas disponiveis."""
    return """# GUIA DE FERRAMENTAS - TecJustica MCP v4

**15 tools. Padrao Deep Agent: descobrir -> navegar -> buscar -> analisar.**

## NAVEGACAO
1. listar_processos() — Descobrir processos, buscar por parte
2. visao_geral_processo("CNJ") — Entrada: metadados + partes + stats + movs
3. ls_documentos("CNJ") — Listar docs sem conteudo (ls)
4. ls_movimentacoes("CNJ") — Timeline de movimentacoes (ls)
5. read_documento("uuid") — Ler conteudo controlado (cat/read)

## BUSCA
6. grep_documentos("termo") — Full-text/regex/ilike no conteudo (grep)
7. grep_movimentacoes("termo") — Full-text em movimentacoes (grep)
8. glob_documentos("CNJ", padrao_tipo="Sentenca") — Filtrar por nome/tipo (glob)
9. localizar_no_documento("uuid", "termo") — Posicoes em 1 doc (bridge grep->read)

## ANALISE
10. stats_documentos("CNJ") — Contagens agregadas, zero texto
11. analisar("CNJ", "pergunta") — Analise com LLM

## PRECEDENTES
12. buscar_precedentes("tema") — Sumulas, temas repetitivos, IRDR (BNP/CNJ)

## UTILIDADE
13. calculadora("calcular", expressao="...") — Calculos matematicos e prazos processuais
14. data_hora_atual() — Data/hora atual com dia da semana
15. whoami — Identidade do usuario

## FLUXO TIPICO
listar_processos -> visao_geral -> grep_documentos -> localizar -> read_documento -> analisar

## PROMPTS PRONTOS
- analise_completa — Analise sistematica completa
- parecer_tecnico — Parecer juridico formal
- due_diligence — Analise para acordo/M&A
- preparar_audiencia — Briefing para audiencia
- estrategia_recursal — Avaliar recursos

## FORMATO CNJ
NNNNNNN-DD.AAAA.J.TR.OOOO (ex: 1234567-89.2024.8.26.0100)"""


# ==================== MAIN ====================

if __name__ == "__main__":
    # Executa servidor
    mcp.run(
        transport="streamable-http",
        host="0.0.0.0",
        port=8000,
    )
