"""Corrige 'parametro opcional antes de obrigatorio' (deprecated no PHP 8.0).

- actions de controller (associadas por nome pelo Yii): move os obrigatorios para o inicio;
- metodos chamados posicionalmente: remove o default dos opcionais que precedem o ultimo obrigatorio.
"""
import re
import sys
from pathlib import Path


def _dividir(lista: str) -> list:
    partes, nivel, atual = [], 0, ""
    for ch in lista:
        if ch in "([":
            nivel += 1
        elif ch in ")]":
            nivel -= 1
        if ch == "," and nivel == 0:
            partes.append(atual)
            atual = ""
        else:
            atual += ch
    if atual.strip():
        partes.append(atual)
    return partes


def corrigir(arquivo: Path, metodo: str, modo: str) -> None:
    texto = arquivo.read_text(encoding="utf8")
    m = re.search(r"function\s+" + re.escape(metodo) + r"\s*\(", texto)
    if not m:
        raise SystemExit(f"{metodo} nao encontrado em {arquivo}")
    ini, nivel, i = m.end(), 1, m.end()
    while nivel:
        nivel += {"(": 1, ")": -1}.get(texto[i], 0)
        i += 1
    fim = i - 1
    bruto = texto[ini:fim]
    partes = _dividir(bruto)
    multilinha = "\n" in bruto
    limpas = [p.strip() for p in partes]
    tem_default = ["=" in p for p in limpas]
    if modo == "action":
        novas = [p for p, d in zip(limpas, tem_default) if not d] + [p for p, d in zip(limpas, tem_default) if d]
    else:
        ultimo_obrig = max(i for i, d in enumerate(tem_default) if not d)
        novas = [re.sub(r"\s*=.*$", "", p) if (d and i < ultimo_obrig) else p
                 for i, (p, d) in enumerate(zip(limpas, tem_default))]
    if multilinha:
        recuo = re.match(r"\n(\s*)", bruto).group(1)
        fecho = re.search(r"\n(\s*)$", bruto)
        novo = "\n" + ",\n".join(recuo + p for p in novas) + ("\n" + fecho.group(1) if fecho else "")
    else:
        novo = ", ".join(novas)
    arquivo.write_text(texto[:ini] + novo + texto[fim:], encoding="utf8", newline="")
    print(f"{arquivo}::{metodo} [{modo}] -> {', '.join(novas)}")


if __name__ == "__main__":
    corrigir(Path(sys.argv[1]), sys.argv[2], sys.argv[3])
