"""Verificacoes estaticas do codigo migrado (rodam sobre a worktree accia-php83)."""
import re
import unittest
from pathlib import Path

RAIZ = Path(__file__).resolve().parents[3]
IGNORAR = ("vendor", "runtime", ".git", "web/assets", "tools", "docs", ".superpowers")
# modulo nao registrado em config/web.php e com namespace igual ao de modules/operational: nunca e carregado
MORTOS = (
    "modules/operational-old/",
    # biblioteca de terceiros sem nenhuma referencia no codigo (grep "PHPlot" fora do proprio arquivo = vazio)
    "components/PHPlot.php",
)


def _php_proprios():
    for p in RAIZ.rglob("*.php"):
        rel = p.relative_to(RAIZ).as_posix()
        if not rel.startswith(IGNORAR):
            yield rel, p.read_text(encoding="utf8", errors="replace")


class CodigoTest(unittest.TestCase):
    def test_sem_sdk_pagseguro(self):
        achados = [rel for rel, txt in _php_proprios() if "\\PagSeguro\\" in txt]
        self.assertEqual(achados, [])

    def test_sem_view_pagseguro(self):
        self.assertFalse((RAIZ / "views/licenca/pagseguro.php").exists())

    def test_sem_lightbox_pagseguro(self):
        self.assertNotIn("pagseguro.lightbox.js", (RAIZ / "views/layouts/main_1.php").read_text(encoding="utf8"))


    def test_sem_funcoes_obsoletas_no_php8(self):
        padrao = re.compile(r"(?<![\w>:$.])(utf8_decode|utf8_encode|each|strftime|create_function|money_format)\s*\(")
        achados = []
        for rel, txt in _php_proprios():
            if rel.startswith(MORTOS):
                continue
            for n, linha in enumerate(txt.splitlines(), 1):
                codigo = linha.split("//")[0]
                if padrao.search(codigo) and not codigo.lstrip().startswith(("*", "#")):
                    achados.append(f"{rel}:{n}")
        self.assertEqual(achados, [])


    def test_filtros_genericsearch_sao_static(self):
        # chamados como GenericSearch::filterMy...() em ~350 lugares; no PHP 8 metodo de instancia => Error
        txt = (RAIZ / "models/GenericSearch.php").read_text(encoding="utf8", errors="replace")
        nao_static = re.findall(r"public\s+function\s+(filterMy\w+)", txt)
        self.assertEqual(nao_static, [])


    def test_metodos_chamados_estaticamente_sao_static(self):
        # alvos levantados pelo PHPStan ("Static call to instance method"): Error no PHP 8
        bs = chr(92)
        faltando = []
        for alvo in (RAIZ / "tools/migracao-php83/fixtures/chamadas-estaticas.txt").read_text().split():
            classe, metodo = alvo.split("::")
            rel = classe.replace("app" + bs, "", 1).replace(bs, "/") + ".php"
            txt = (RAIZ / rel).read_text(encoding="utf8", errors="replace")
            if not re.search(r"(public|protected|private)\s+static\s+function\s+" + metodo + r"\s*\(", txt):
                faltando.append(alvo)
        self.assertEqual(faltando, [])


if __name__ == "__main__":
    unittest.main()
