import re
import json
from mcp.server.fastmcp import FastMCP


def register(mcp: FastMCP):

    @mcp.tool()
    def fluig_validar_form_html(html_src: str) -> str:
        """
        Analisa o HTML de um formulario Fluig e detecta problemas: imports faltando,
        wrapper incorreto, campos sem name, padroes errados do Style Guide,
        nomes de campo fora do padrao snake_case, campos acima de 30 chars,
        falta de col-xs-12, ausencia de jQuery/Mustache, painel e custom.js.

        Args:
            html_src: Conteudo HTML completo do formulario.
        """
        erros = []
        avisos = []
        ok = []

        # --- Imports obrigatorios ---
        if "fluig-style-guide.min.css" in html_src:
            ok.append("Import CSS fluig-style-guide.min.css presente")
        else:
            erros.append(
                'IMPORT FALTANDO: <link rel="stylesheet" '
                'href="/style-guide/css/fluig-style-guide.min.css" />'
            )

        if "fluig-style-guide-ie.min.css" in html_src:
            ok.append("Import CSS IE presente")
        else:
            avisos.append("IMPORT AUSENTE (recomendado): fluig-style-guide-ie.min.css")

        if "fluig-style-guide.min.js" in html_src:
            ok.append("Import JS fluig-style-guide.min.js presente")
        else:
            erros.append(
                'IMPORT FALTANDO: <script src="/style-guide/js/'
                'fluig-style-guide.min.js"></script>'
            )

        # jQuery import check
        if "jquery" in html_src.lower():
            ok.append("jQuery import detectado")
        else:
            avisos.append(
                "IMPORT AUSENTE (recomendado): jQuery (3.7.1). "
                "Necessario para componentes interativos."
            )

        # Mustache import check
        if "mustache" in html_src.lower():
            ok.append("Mustache JS import detectado")
        else:
            avisos.append(
                "IMPORT AUSENTE (recomendado): Mustache JS (2.3.2). "
                "Necessario para templates de dados."
            )

        # --- Wrapper obrigatorio ---
        if 'class="fluig-style-guide"' in html_src:
            ok.append("Wrapper div.fluig-style-guide presente")
        else:
            erros.append(
                'WRAPPER FALTANDO: todo o conteudo deve estar dentro de '
                '<div class="fluig-style-guide">'
            )

        # --- Presenca de pelo menos um panel ---
        if "panel-default" in html_src or "panel-primary" in html_src:
            ok.append("Pelo menos um panel encontrado")
        else:
            avisos.append(
                "PANEL AUSENTE: formularios devem ter pelo menos um "
                "panel para agrupar campos."
            )

        # --- custom.js reference ---
        if "custom.js" in html_src:
            ok.append("Referencia a custom.js presente")
        else:
            avisos.append(
                "CUSTOM.JS AUSENTE: recomendado incluir "
                '<script src="custom.js"></script> para logica do formulario.'
            )

        # --- Campos sem name ---
        inputs_sem_name = re.findall(
            r"<input(?![^>]*name=)[^>]*>", html_src, re.IGNORECASE
        )
        inputs_sem_name = [
            i
            for i in inputs_sem_name
            if 'type="hidden"' not in i
            and 'type="button"' not in i
            and 'type="submit"' not in i
        ]
        if inputs_sem_name:
            erros.append(
                f"CAMPOS SEM ATRIBUTO name ({len(inputs_sem_name)} encontrado(s)): "
                + "; ".join(inputs_sem_name[:3])
            )
        else:
            ok.append("Todos os inputs tem atributo name")

        # --- Field name validation: snake_case and max 30 chars ---
        all_names = re.findall(r'name="([^"]+)"', html_src)
        for field_name in all_names:
            # Skip Fluig platform fields
            if field_name.startswith("WK") or field_name.startswith("form"):
                continue
            # Check max length
            if len(field_name) > 30:
                erros.append(
                    f"NOME LONGO: campo '{field_name}' tem {len(field_name)} "
                    f"caracteres (max 30)."
                )
            # Check snake_case: warn if camelCase or spaces
            if " " in field_name:
                avisos.append(
                    f"NOME COM ESPACO: campo '{field_name}' — "
                    "usar snake_case (ex: nome_completo)."
                )
            elif re.search(r"[A-Z]", field_name):
                avisos.append(
                    f"NOME CAMELCASE: campo '{field_name}' — "
                    "recomendado usar snake_case (ex: nome_completo)."
                )

        # --- col-xs-12 check on column divs ---
        col_divs = re.findall(
            r'<div\s+class="([^"]*col-(?:sm|md|lg)-\d+[^"]*)"', html_src
        )
        missing_xs = [
            cls for cls in col_divs if "col-xs-" not in cls
        ]
        if missing_xs:
            avisos.append(
                f"COL-XS-12 AUSENTE em {len(missing_xs)} coluna(s): "
                "adicionar col-xs-12 para fallback mobile. "
                f"Exemplos: {', '.join(missing_xs[:3])}"
            )
        elif col_divs:
            ok.append("Todas as colunas incluem col-xs-* para mobile")

        # --- Campos sem form-control ---
        inputs_sem_class = re.findall(
            r'<input(?![^>]*form-control)[^>]*type="text"[^>]*>',
            html_src,
            re.IGNORECASE,
        )
        if inputs_sem_class:
            avisos.append(
                f"INPUTS SEM class='form-control' ({len(inputs_sem_class)} "
                "encontrado(s)) — recomendado para estilo correto"
            )

        # --- Anexo sem data-process-id ---
        if "data-attachments" in html_src:
            if "data-process-id" not in html_src:
                erros.append(
                    "ANEXO INCOMPLETO: data-attachments presente mas "
                    "data-process-id ausente (obrigatorio)"
                )
            elif "data-instance-id" not in html_src:
                erros.append(
                    "ANEXO INCOMPLETO: data-attachments presente mas "
                    "data-instance-id ausente (obrigatorio)"
                )
            else:
                ok.append("Componente de anexo configurado corretamente")

        # --- form com action (normalmente nao usado no Fluig) ---
        if 'action="' in html_src and 'action=""' not in html_src:
            avisos.append(
                "FORM com action definido — no Fluig o submit e gerenciado "
                "pela plataforma, verifique se e intencional"
            )

        resultado = {
            "status": "OK" if not erros else "COM ERROS",
            "total_erros": len(erros),
            "total_avisos": len(avisos),
            "erros": erros,
            "avisos": avisos,
            "verificacoes_ok": ok,
        }

        return json.dumps(resultado, ensure_ascii=False, indent=2)

    @mcp.tool()
    def fluig_validar_dataset_js(codigo: str) -> str:
        """
        Analisa o codigo JavaScript de um dataset Fluig e detecta problemas comuns:
        assinaturas erradas, uso incorreto de APIs, mas praticas.

        Args:
            codigo: Codigo JS completo do dataset.
        """
        erros = []
        avisos = []
        ok = []

        # createDataset obrigatorio
        if "function createDataset" in codigo:
            ok.append("Funcao createDataset presente")
        else:
            erros.append(
                "FUNCAO FALTANDO: createDataset(fields, constraints, sortFields) "
                "e obrigatoria"
            )

        # Assinatura correta
        assinatura_correta = re.search(
            r"function\s+createDataset\s*\(\s*fields\s*,\s*constraints\s*,"
            r"\s*sortFields\s*\)",
            codigo,
        )
        if "function createDataset" in codigo and not assinatura_correta:
            avisos.append(
                "ASSINATURA: createDataset deve ter exatamente os parametros "
                "(fields, constraints, sortFields)"
            )

        # DatasetFactory.createDataset
        if "DatasetFactory.createDataset()" in codigo:
            ok.append("DatasetFactory.createDataset() presente")
        else:
            erros.append(
                "FALTANDO: var dataset = DatasetFactory.createDataset(); — "
                "necessario para inicializar o dataset"
            )

        # addColumn
        if "addColumn" in codigo:
            ok.append("dataset.addColumn() presente")
        else:
            erros.append(
                "FALTANDO: dataset.addColumn('nome') — definir as colunas do dataset"
            )

        # return dataset
        if "return dataset" in codigo:
            ok.append("return dataset presente")
        else:
            erros.append("FALTANDO: return dataset; ao final de createDataset")

        # addRow
        if "addRow" in codigo:
            ok.append("dataset.addRow() presente")
        else:
            avisos.append(
                "AVISO: dataset.addRow() nao encontrado — sem dados sendo adicionados"
            )

        # console.log em producao
        if "console.log" in codigo:
            avisos.append(
                "console.log detectado — remover em producao (usar log.info() no Fluig)"
            )

        # alert() em dataset
        if "alert(" in codigo:
            erros.append("alert() em dataset server-side nao funciona — remover")

        # document/window em dataset
        if "document." in codigo or "window." in codigo:
            erros.append(
                "document/window nao existem em contexto server-side de dataset — remover"
            )

        # $() jQuery em dataset
        if re.search(r"\$\(", codigo):
            erros.append(
                "jQuery ($) nao esta disponivel em datasets server-side — remover"
            )

        resultado = {
            "status": "OK" if not erros else "COM ERROS",
            "total_erros": len(erros),
            "total_avisos": len(avisos),
            "erros": erros,
            "avisos": avisos,
            "verificacoes_ok": ok,
        }

        return json.dumps(resultado, ensure_ascii=False, indent=2)

    @mcp.tool()
    def fluig_validar_evento_js(
        codigo: str, tipo_evento: str = "workflow"
    ) -> str:
        """
        Analisa um script de evento Fluig (workflow ou formulario) e detecta
        APIs incorretas, contexto errado e problemas comuns.

        Args:
            codigo: Codigo JS completo do evento.
            tipo_evento: 'workflow' ou 'form'.
        """
        erros = []
        avisos = []
        ok = []

        if tipo_evento == "workflow":
            apis_invalidas_workflow = [
                "getValue",
                "setValue",
                "$",
                "document.",
                "window.",
                "alert(",
            ]

            for api in apis_invalidas_workflow:
                if api in codigo:
                    erros.append(
                        f"API invalida em evento workflow: '{api}' nao esta "
                        "disponivel neste contexto"
                    )

            if "ServiceManager.getService" in codigo:
                ok.append(
                    "ServiceManager.getService() — uso correto para acessar servicos"
                )

            if (
                "log.info" in codigo
                or "log.error" in codigo
                or "log.warn" in codigo
            ):
                ok.append("Logging com log.info/error/warn presente")
            else:
                avisos.append(
                    "Sem logging — recomendado adicionar log.info() para auditoria"
                )

            if "try" in codigo and "catch" in codigo:
                ok.append("Tratamento de erro com try/catch presente")
            else:
                avisos.append(
                    "Sem try/catch — recomendado para eventos de workflow para "
                    "evitar falhas silenciosas"
                )

            if "console.log" in codigo:
                avisos.append(
                    "console.log em evento workflow — preferir log.info()"
                )

        else:  # form
            if "getValue(" in codigo or "setValue(" in codigo:
                ok.append(
                    "getValue/setValue presentes — correto para eventos de formulario"
                )

            if "DatasetFactory" in codigo:
                avisos.append(
                    "DatasetFactory em evento de formulario — verificar se e "
                    "server-side (beforeFormSave/validateForm) ou client-side "
                    "(afterRenderForm). Client-side deve usar chamada REST."
                )

            if re.search(r"\$\(", codigo):
                avisos.append(
                    "jQuery ($) detectado — OK apenas em eventos client-side "
                    "(afterRenderForm, afterStateChange). Nao usar em "
                    "validateForm ou beforeFormSave."
                )

            if "alert(" in codigo:
                avisos.append(
                    "alert() — preferir FLUIGC.toast() ao inves de alert nativo"
                )

        resultado = {
            "status": "OK" if not erros else "COM ERROS",
            "tipo_evento": tipo_evento,
            "total_erros": len(erros),
            "total_avisos": len(avisos),
            "erros": erros,
            "avisos": avisos,
            "verificacoes_ok": ok,
        }

        return json.dumps(resultado, ensure_ascii=False, indent=2)
