"""API Tools: Workflow / BPM (v2)"""
import json
from urllib.parse import quote as urlquote
from mcp.server.fastmcp import FastMCP
from http_client import fluig_get, fluig_post, fluig_delete


def register(mcp: FastMCP):

    # ── PROCESSOS ──────────────────────────────────────────────

    @mcp.tool()
    async def fluig_wf_listar_processos(
        processo_id: str = "",
        ativo: str = "",
        publico: str = "",
        pagina: int = 0,
        tamanho: int = 20,
        ordem: str = "",
        expand: str = "",
    ) -> str:
        """
        Lista todos os processos BPM disponiveis.

        Args:
            processo_id: Filtrar por ID do processo.
            ativo: Filtrar por status ativo: 'true' ou 'false'.
            publico: Filtrar por processos publicos: 'true' ou 'false'.
            pagina: Pagina de resultados.
            tamanho: Itens por pagina.
            ordem: Campo de ordenacao.
            expand: Campos a expandir (ex: 'activities').
        """
        params: dict = {"page": pagina, "pageSize": tamanho}
        if processo_id:
            params["processId"] = processo_id
        if ativo:
            params["active"] = ativo
        if publico:
            params["public"] = publico
        if ordem:
            params["order"] = ordem
        if expand:
            params["expand"] = expand
        return await fluig_get("/api/v2/processes", params)

    @mcp.tool()
    async def fluig_wf_iniciar(body_json: str) -> str:
        """
        Cria/inicia uma nova instancia de processo BPM.

        Args:
            body_json: JSON object com dados do processo (ProcessSimpleCreate). Ex: '{"processId":"PROC_001","activities":[{"activityId":1}]}'.
        """
        try:
            body = json.loads(body_json)
        except json.JSONDecodeError as e:
            return f"Erro: body_json invalido - {e}"
        return await fluig_post("/api/v2/processes", body)

    @mcp.tool()
    async def fluig_wf_obter_processo(processo_id: str) -> str:
        """
        Obtem detalhes de um processo especifico.

        Args:
            processo_id: ID do processo.
        """
        safe_id = urlquote(str(processo_id), safe="")
        return await fluig_get(f"/api/v2/processes/{safe_id}")

    @mcp.tool()
    async def fluig_wf_excluir_processo(processo_id: str) -> str:
        """
        Remove um processo.

        Args:
            processo_id: ID do processo a remover.
        """
        safe_id = urlquote(str(processo_id), safe="")
        return await fluig_delete(f"/api/v2/processes/{safe_id}")

    # ── ATIVIDADES ─────────────────────────────────────────────

    @mcp.tool()
    async def fluig_wf_atividades(
        instancia_id: str = "",
        ativo: str = "",
        sla_status: str = "",
        processo_id: str = "",
        solicitante: str = "",
        responsavel: str = "",
        pagina: int = 0,
        tamanho: int = 20,
        ordem: str = "",
        expand: str = "",
    ) -> str:
        """
        Pesquisa atividades (tarefas) de workflows.

        Args:
            instancia_id: Filtrar por ID da instancia de processo.
            ativo: Filtrar por atividades ativas: 'true' ou 'false'.
            sla_status: Filtrar por status de SLA.
            processo_id: Filtrar por ID do processo.
            solicitante: Filtrar por login do solicitante.
            responsavel: Filtrar por login do responsavel.
            pagina: Pagina de resultados.
            tamanho: Itens por pagina.
            ordem: Campo de ordenacao.
            expand: Campos a expandir.
        """
        params: dict = {"page": pagina, "pageSize": tamanho}
        if instancia_id:
            params["processInstanceId"] = instancia_id
        if ativo:
            params["active"] = ativo
        if sla_status:
            params["slaStatus"] = sla_status
        if processo_id:
            params["processId"] = processo_id
        if solicitante:
            params["requester"] = solicitante
        if responsavel:
            params["assignee"] = responsavel
        if ordem:
            params["order"] = ordem
        if expand:
            params["expand"] = expand
        return await fluig_get("/api/v2/activities", params)

    @mcp.tool()
    async def fluig_wf_atividades_resumo() -> str:
        """Retorna atividades agrupadas por status (resumo)."""
        return await fluig_get("/api/v2/activities/resume")

    @mcp.tool()
    async def fluig_wf_atividades_processo(processo_id: str) -> str:
        """
        Lista atividades de um processo especifico.

        Args:
            processo_id: ID do processo.
        """
        safe_id = urlquote(str(processo_id), safe="")
        return await fluig_get(f"/api/v2/processes/{safe_id}/activities")

    # ── VERSOES ────────────────────────────────────────────────

    @mcp.tool()
    async def fluig_wf_versoes(processo_id: str) -> str:
        """
        Lista as versoes de um processo.

        Args:
            processo_id: ID do processo.
        """
        safe_id = urlquote(str(processo_id), safe="")
        return await fluig_get(f"/api/v2/processes/{safe_id}/process-versions")

    @mcp.tool()
    async def fluig_wf_diagrama(
        processo_id: str,
        versao: str,
    ) -> str:
        """
        Obtem o diagrama SVG de uma versao de processo.

        Args:
            processo_id: ID do processo.
            versao: Numero da versao.
        """
        safe_id = urlquote(str(processo_id), safe="")
        safe_v = urlquote(str(versao), safe="")
        return await fluig_get(f"/api/v2/processes/{safe_id}/process-versions/{safe_v}/diagram")

    @mcp.tool()
    async def fluig_wf_publicar_versao(processo_id: str) -> str:
        """
        Publica (release) a ultima versao de um processo.

        Args:
            processo_id: ID do processo.
        """
        safe_id = urlquote(str(processo_id), safe="")
        return await fluig_post(f"/api/v2/processes/{safe_id}/process-versions/latest/release")

    # ── IMPORTAR / EXPORTAR XML ────────────────────────────────

    @mcp.tool()
    async def fluig_wf_exportar_xml(processo_id: str) -> str:
        """
        Exporta um processo como XML.

        Args:
            processo_id: ID do processo.
        """
        safe_id = urlquote(str(processo_id), safe="")
        return await fluig_get(f"/api/v2/processes/{safe_id}/export/xml")

    @mcp.tool()
    async def fluig_wf_importar_xml(
        processo_id: str,
        body_json: str,
    ) -> str:
        """
        Importa um processo a partir de XML.

        Args:
            processo_id: ID do processo destino.
            body_json: JSON object com o conteudo XML a importar.
        """
        try:
            body = json.loads(body_json)
        except json.JSONDecodeError as e:
            return f"Erro: body_json invalido - {e}"
        safe_id = urlquote(str(processo_id), safe="")
        return await fluig_post(f"/api/v2/processes/{safe_id}/import/xml", body)

    # ── CALCULADORA DE DATAS ───────────────────────────────────

    @mcp.tool()
    async def fluig_wf_calcular_duracao(
        data_inicio: str,
        data_fim: str,
        local_id: str = "",
        period_id: str = "",
    ) -> str:
        """
        Calcula a duracao em segundos uteis entre duas datas.

        Args:
            data_inicio: Data de inicio (formato ISO). Ex: '2026-03-01T08:00:00'.
            data_fim: Data de fim (formato ISO).
            local_id: ID do local/calendario (opcional).
            period_id: ID do periodo (opcional).
        """
        params: dict = {"startDate": data_inicio, "endDate": data_fim}
        if local_id:
            params["localId"] = local_id
        if period_id:
            params["periodId"] = period_id
        return await fluig_get("/api/v2/date-calculator/duration", params)

    @mcp.tool()
    async def fluig_wf_calcular_data_fim(
        data_inicio: str,
        segundos: int,
    ) -> str:
        """
        Calcula a data de termino a partir de uma data inicial e duracao em segundos.

        Args:
            data_inicio: Data de inicio (formato ISO).
            segundos: Duracao em segundos uteis.
        """
        params = {"startDate": data_inicio, "seconds": segundos}
        return await fluig_get("/api/v2/date-calculator/end-date", params)
