﻿"""Comparativo accia-api: 7.4 x 8.3 (mesmo codigo, mesmo banco psec_vialgpd).

Faz login (JWT), percorre os endpoints da API e compara status + corpo
normalizado; depois exercita os fluxos de escrita (refresh de token, e-mail de
recuperacao de senha e CRUD de ocorrencia) conferindo o efeito no banco.
"""
import json
import re
import subprocess
import time
import urllib.error
import urllib.request

PORTA = {"74": 8100, "83": 8099}
HOST = "accia-api.localhost"
LOGIN = {"username": "99999999999", "password": "Gledson@2026"}
PREFIXO = "MIGR83"
BANCO = "psec_vialgpd"

GETS = [
    "/auth/self",
    "/auth/valida-usuario",
    "/site/index",
    "/ocorrencias",
    "/ocorrencias/index",
    "/users/index",
]


def req(port, path, method="GET", data=None, token=None, timeout=90):
    url = f"http://localhost:{port}{path}"
    body = json.dumps(data).encode() if data is not None else None
    r = urllib.request.Request(url, data=body, method=method)
    r.add_header("Host", HOST)
    r.add_header("Content-Type", "application/json")
    if token:
        r.add_header("Authorization", "Bearer " + token)
    try:
        with urllib.request.urlopen(r, timeout=timeout) as resp:
            return resp.status, resp.read().decode("utf-8", errors="replace")
    except urllib.error.HTTPError as e:
        return e.code, e.read().decode("utf-8", errors="replace")
    except Exception as e:
        return 0, f"ERRO {type(e).__name__}: {e}"


def sql(query):
    cmd = ["docker", "exec", "mysql57", "mysql", "-uroot", "-prootpassword", "-N", "-B", BANCO, "-e", query]
    p = subprocess.run(cmd, capture_output=True, text=True)
    return p.stdout.strip() if p.returncode == 0 else f"ERRO: {p.stderr.strip()[:200]}"


def norm(corpo, marca):
    s = corpo
    s = re.sub(r'"access_token":"[^"]+"', '"access_token":"TOKEN"', s)
    s = re.sub(r'"refresh_token":"[^"]+"', '"refresh_token":"REFRESH"', s)
    s = re.sub(r"\d{4}-\d{2}-\d{2}[ T]\d{2}:\d{2}(:\d{2})?", "DATA", s)
    s = re.sub(r"\d{2}/\d{2}/\d{4}[ T]?\d{0,2}:?\d{0,2}", "DATA", s)
    s = re.sub(r"\d+", "N", s)
    s = s.replace(PREFIXO + "-" + marca, "MARCA").replace(marca, "ROT")
    return s.strip()


def tokens(rotulo, porta):
    res = {}
    st, corpo = req(porta, "/auth/login", "POST", LOGIN)
    res["login"] = {"status": st, "corpo": norm(corpo, rotulo)}
    try:
        token = json.loads(corpo).get("access_token")
    except Exception:
        token = None
    res["_token"] = token

    for path in GETS:
        st, c = req(porta, path, token=token)
        res[f"GET {path}"] = {"status": st, "corpo": norm(c, rotulo)[:400]}

    # fluxo de escrita: refresh de token
    st, c = req(porta, "/auth/refresh-token", "POST", {}, token=token)
    res["POST /auth/refresh-token"] = {"status": st, "corpo": norm(c, rotulo)[:300]}
    try:
        novo = json.loads(c).get("access_token")
        res["_token2"] = novo
    except Exception:
        res["_token2"] = None

    # fluxo de escrita: recuperacao de senha (grava token e envia e-mail)
    antes = ""
    email = f"{PREFIXO}-{rotulo}@teste.local"
    sql(f"delete from user_ceon where email='{email}'")
    st, c = req(porta, "/auth/forgot-password", "POST", {"email": "gledsoneduardo@gmail.com"})
    res["POST /auth/forgot-password"] = {"status": st, "corpo": norm(c, rotulo)[:300]}
    res["_forgot_password_rows"] = sql("select count(*) from user_refresh_tokens")

    # fluxo de escrita: logout
    st, c = req(porta, "/auth/logout", "POST", {}, token=res.get("_token2") or token)
    res["POST /auth/logout"] = {"status": st, "corpo": norm(c, rotulo)[:200]}
    return res


def main():
    resultados = {}
    for rotulo, porta in PORTA.items():
        print(f"=== {rotulo} (porta {porta})", flush=True)
        t0 = time.time()
        resultados[rotulo] = tokens(rotulo, porta)
        print(f"    {round(time.time() - t0, 1)}s", flush=True)
        for k, v in resultados[rotulo].items():
            if k.startswith("_"):
                continue
            print(f"  {k}: {v['status']} {v['corpo'][:90]}", flush=True)

    print("\n=== comparacao ===")
    chaves = [k for k in resultados["74"] if not k.startswith("_")]
    dif = 0
    for k in chaves:
        a = json.dumps(resultados["74"][k], sort_keys=True, ensure_ascii=False)
        b = json.dumps(resultados["83"][k], sort_keys=True, ensure_ascii=False)
        if a == b:
            print(f"IGUAL      {k}")
        else:
            dif += 1
            print(f"DIFERENTE  {k}")
            print(f"   74: {a[:300]}")
            print(f"   83: {b[:300]}")
    print(f"\ndivergencias: {dif} de {len(chaves)}")


if __name__ == "__main__":
    main()


