"""Fase 3 — API Tools: ECM Forms / Cards (v2 — cardindex)"""
import json
from urllib.parse import quote as urlquote
from mcp.server.fastmcp import FastMCP
from http_client import fluig_get, fluig_post, fluig_put, fluig_patch, fluig_delete


def register(mcp: FastMCP):

    # ── CARDINDEX (formularios ECM) ─────────────────────────────

    @mcp.tool()
    async def fluig_cardindex_listar(
        pagina: int = 0,
        tamanho: int = 20,
    ) -> str:
        """
        Lista os formularios ECM (cardindex) cadastrados no Fluig.

        Args:
            pagina: Pagina de resultados.
            tamanho: Itens por pagina.
        """
        return await fluig_get(
            "/api/v2/cardindex",
            params={"page": pagina, "pageSize": tamanho},
        )

    @mcp.tool()
    async def fluig_cardindex_criar(body_json: str) -> str:
        """
        Cria um novo formulario ECM (cardindex).

        Args:
            body_json: JSON object com dados do formulario ECM.
        """
        try:
            body = json.loads(body_json)
        except json.JSONDecodeError as e:
            return f"Erro: body_json invalido - {e}"
        return await fluig_post("/api/v2/cardindex", body)

    @mcp.tool()
    async def fluig_cardindex_atualizar(body_json: str) -> str:
        """
        Atualiza um formulario ECM existente (PUT completo).

        Args:
            body_json: JSON object com dados completos do formulario ECM.
        """
        try:
            body = json.loads(body_json)
        except json.JSONDecodeError as e:
            return f"Erro: body_json invalido - {e}"
        return await fluig_put("/api/v2/cardindex", body)

    @mcp.tool()
    async def fluig_cardindex_patch(body_json: str) -> str:
        """
        Atualiza parcialmente um formulario ECM (PATCH).

        Args:
            body_json: JSON object com os campos a atualizar.
        """
        try:
            body = json.loads(body_json)
        except json.JSONDecodeError as e:
            return f"Erro: body_json invalido - {e}"
        return await fluig_patch("/api/v2/cardindex", body)

    @mcp.tool()
    async def fluig_cardindex_html(
        documento_id: int,
        atividade_id: int = 0,
    ) -> str:
        """
        Retorna o HTML renderizado de um formulario ECM.

        Args:
            documento_id: ID do documento/formulario.
            atividade_id: ID da atividade (opcional, 0 = sem contexto de atividade).
        """
        params: dict = {"documentId": documento_id}
        if atividade_id:
            params["activityId"] = atividade_id
        return await fluig_get("/api/v2/cardindex/html", params)

    # ── CARDS (registros) ───────────────────────────────────────

    @mcp.tool()
    async def fluig_card_listar(
        documento_id: int,
        filtro_odata: str = "",
        pagina: int = 0,
        tamanho: int = 20,
    ) -> str:
        """
        Lista registros (cards) de um formulario ECM com suporte a filtros ODATA.

        Args:
            documento_id: ID do documento/formulario.
            filtro_odata: Filtro ODATA opcional. Ex: "campo1 eq 'valor' and campo2 gt 10".
            pagina: Pagina de resultados.
            tamanho: Registros por pagina.
        """
        safe_id = urlquote(str(documento_id), safe="")
        params: dict = {"page": pagina, "pageSize": tamanho}
        if filtro_odata:
            params["$filter"] = filtro_odata
        return await fluig_get(f"/api/v2/cardindex/{safe_id}/cards", params)

    @mcp.tool()
    async def fluig_card_obter(
        documento_id: int,
        card_id: int,
    ) -> str:
        """
        Obtem um registro especifico de um formulario pelo ID.

        Args:
            documento_id: ID do documento/formulario.
            card_id: ID do registro/card.
        """
        safe_doc = urlquote(str(documento_id), safe="")
        safe_card = urlquote(str(card_id), safe="")
        return await fluig_get(f"/api/v2/cardindex/{safe_doc}/cards/{safe_card}")

    @mcp.tool()
    async def fluig_card_criar(
        documento_id: int,
        campos_json: str,
    ) -> str:
        """
        Cria um novo registro (card) em um formulario ECM.

        Args:
            documento_id: ID do documento/formulario.
            campos_json: JSON object com os campos e valores. Ex: '{"nome_cliente":"Joao","cpf":"000.000.000-00"}'.
        """
        try:
            body = json.loads(campos_json)
        except json.JSONDecodeError as e:
            return f"Erro: campos_json invalido - {e}"
        safe_id = urlquote(str(documento_id), safe="")
        return await fluig_post(f"/api/v2/cardindex/{safe_id}/cards", body)

    @mcp.tool()
    async def fluig_card_atualizar(
        documento_id: int,
        card_id: int,
        campos_json: str,
    ) -> str:
        """
        Atualiza um registro existente (PUT completo).

        Args:
            documento_id: ID do documento/formulario.
            card_id: ID do registro a atualizar.
            campos_json: JSON object com todos os campos e valores.
        """
        try:
            body = json.loads(campos_json)
        except json.JSONDecodeError as e:
            return f"Erro: campos_json invalido - {e}"
        safe_doc = urlquote(str(documento_id), safe="")
        safe_card = urlquote(str(card_id), safe="")
        return await fluig_put(f"/api/v2/cardindex/{safe_doc}/cards/{safe_card}", body)

    @mcp.tool()
    async def fluig_card_excluir(
        documento_id: int,
        card_id: int,
    ) -> str:
        """
        Remove um registro de formulario.

        Args:
            documento_id: ID do documento/formulario.
            card_id: ID do registro a excluir.
        """
        safe_doc = urlquote(str(documento_id), safe="")
        safe_card = urlquote(str(card_id), safe="")
        return await fluig_delete(f"/api/v2/cardindex/{safe_doc}/cards/{safe_card}")

    # ── CHILDREN (registros filho / pai-filho) ──────────────────

    @mcp.tool()
    async def fluig_card_filho_listar(
        documento_id: int,
        card_id: int,
    ) -> str:
        """
        Lista os registros filho de um card (relacao pai-filho).

        Args:
            documento_id: ID do documento/formulario.
            card_id: ID do registro pai.
        """
        safe_doc = urlquote(str(documento_id), safe="")
        safe_card = urlquote(str(card_id), safe="")
        return await fluig_get(f"/api/v2/cardindex/{safe_doc}/cards/{safe_card}/children")

    @mcp.tool()
    async def fluig_card_filho_criar(
        documento_id: int,
        card_id: int,
        campos_json: str,
    ) -> str:
        """
        Cria um registro filho vinculado a um card pai.

        Args:
            documento_id: ID do documento/formulario.
            card_id: ID do registro pai.
            campos_json: JSON object com campos e valores do registro filho.
        """
        try:
            body = json.loads(campos_json)
        except json.JSONDecodeError as e:
            return f"Erro: campos_json invalido - {e}"
        safe_doc = urlquote(str(documento_id), safe="")
        safe_card = urlquote(str(card_id), safe="")
        return await fluig_post(f"/api/v2/cardindex/{safe_doc}/cards/{safe_card}/children", body)

    @mcp.tool()
    async def fluig_card_filho_obter(
        documento_id: int,
        card_id: int,
        row: int,
    ) -> str:
        """
        Obtem um registro filho especifico pela linha.

        Args:
            documento_id: ID do documento/formulario.
            card_id: ID do registro pai.
            row: Numero da linha do registro filho.
        """
        safe_doc = urlquote(str(documento_id), safe="")
        safe_card = urlquote(str(card_id), safe="")
        safe_row = urlquote(str(row), safe="")
        return await fluig_get(f"/api/v2/cardindex/{safe_doc}/cards/{safe_card}/children/{safe_row}")

    @mcp.tool()
    async def fluig_card_filho_atualizar(
        documento_id: int,
        card_id: int,
        row: int,
        campos_json: str,
    ) -> str:
        """
        Atualiza um registro filho especifico.

        Args:
            documento_id: ID do documento/formulario.
            card_id: ID do registro pai.
            row: Numero da linha do registro filho.
            campos_json: JSON object com campos e valores atualizados.
        """
        try:
            body = json.loads(campos_json)
        except json.JSONDecodeError as e:
            return f"Erro: campos_json invalido - {e}"
        safe_doc = urlquote(str(documento_id), safe="")
        safe_card = urlquote(str(card_id), safe="")
        safe_row = urlquote(str(row), safe="")
        return await fluig_put(
            f"/api/v2/cardindex/{safe_doc}/cards/{safe_card}/children/{safe_row}", body
        )

    @mcp.tool()
    async def fluig_card_filho_excluir(
        documento_id: int,
        card_id: int,
        row: int,
    ) -> str:
        """
        Remove um registro filho especifico.

        Args:
            documento_id: ID do documento/formulario.
            card_id: ID do registro pai.
            row: Numero da linha do registro filho a excluir.
        """
        safe_doc = urlquote(str(documento_id), safe="")
        safe_card = urlquote(str(card_id), safe="")
        safe_row = urlquote(str(row), safe="")
        return await fluig_delete(
            f"/api/v2/cardindex/{safe_doc}/cards/{safe_card}/children/{safe_row}"
        )
