"""Teste US-005 (PRD 5.6): audit login RAR + ciclu de viata trimiteri (worker)."""

from __future__ import annotations

import json
import os
import tempfile

import pytest

from app.rar_client import RarAuthError


@pytest.fixture()
def env(monkeypatch):
    tmp = tempfile.mkdtemp()
    monkeypatch.setenv("AUTOPASS_DB_PATH", os.path.join(tmp, "wo.db"))
    monkeypatch.setenv("AUTOPASS_LOG_DIR", os.path.join(tmp, "logs"))
    from app.config import get_settings
    get_settings.cache_clear()
    from app.db import get_connection, init_db
    init_db()
    conn = get_connection()
    settings = get_settings()
    yield conn, settings
    conn.close()
    get_settings.cache_clear()


_CONTENT = {"vin": "WVWZZZ1KZAW000123", "nr_inmatriculare": "B999TST",
            "data_prestatie": "2026-06-15", "odometru_final": "123456",
            "prestatii": [{"cod_prestatie": "OE-1"}], "sistem_reparat": "null"}


def _events(conn, tip=None):
    if tip:
        return conn.execute("SELECT * FROM app_events WHERE tip=?", (tip,)).fetchall()
    return conn.execute("SELECT * FROM app_events").fetchall()


class FakeRar:
    def __init__(self, *, token="JWT-TEST", login_exc=None, post_result=None):
        self.token = token
        self.login_exc = login_exc
        self.post_result = post_result if post_result is not None else {"id": 1000}
        self.closed = False

    def login(self, email, password):
        if self.login_exc:
            raise self.login_exc
        return self.token

    def get_nomenclator(self, token):
        return []

    def post_prezentare(self, token, payload):
        return self.post_result

    def close(self):
        self.closed = True


def test_login_reusit_logat(env, monkeypatch):
    conn, settings = env
    import app.worker.__main__ as w
    monkeypatch.setattr(w, "RarClient", lambda s, **kw: FakeRar())
    sessions = w.AccountSessions(settings)
    tok = sessions.get_token(conn, 2, {"email": "a@b.ro", "password": "secretaXY"})
    assert tok == "JWT-TEST"
    rows = _events(conn, "rar_login")
    assert len(rows) == 1
    assert rows[0]["account_id"] == 2
    ctx = rows[0]["context_json"]
    assert "ok" in ctx
    # fara parola in clar nicaieri
    assert "secretaXY" not in (rows[0]["mesaj"] or "")
    assert "secretaXY" not in (ctx or "")


def test_login_401_logat_fara_parola(env, monkeypatch):
    conn, settings = env
    import app.worker.__main__ as w
    monkeypatch.setattr(w, "RarClient", lambda s, **kw: FakeRar(login_exc=RarAuthError("401", status_code=401)))
    sessions = w.AccountSessions(settings)
    with pytest.raises(RarAuthError):
        sessions.get_token(conn, 3, {"email": "a@b.ro", "password": "parolaGRESITA"})
    rows = _events(conn, "rar_login")
    assert len(rows) == 1
    assert rows[0]["nivel"] == "WARNING"
    assert "esuat" in rows[0]["context_json"]
    assert "parolaGRESITA" not in (rows[0]["context_json"] or "")
    assert "parolaGRESITA" not in (rows[0]["mesaj"] or "")


def test_tranzitie_sent_si_error_logate(env, monkeypatch):
    conn, settings = env
    import app.worker.__main__ as w
    from app.accounts import create_account
    acct = create_account(conn, "Service Worker Obs", active=True)
    cur = conn.execute(
        "INSERT INTO submissions (idempotency_key, account_id, status, payload_json) VALUES (?, ?, 'sending', ?)",
        (f"k-{os.urandom(4).hex()}", acct, json.dumps(_CONTENT)),
    )
    sid = int(cur.lastrowid)
    claimed = {"id": sid, "account_id": acct, "content": _CONTENT}
    rar = FakeRar()
    res = w.process_one(conn, settings, rar, "tok", claimed)
    assert res == "sent"
    assert len(_events(conn, "submission_sent")) == 1
    assert _events(conn, "submission_sent")[0]["account_id"] == 2

    # eroare 4xx nerecuperabila -> submission_error
    from app.rar_client import RarError
    cur2 = conn.execute(
        "INSERT INTO submissions (idempotency_key, account_id, status, payload_json) VALUES (?, 2, 'sending', ?)",
        (f"k-{os.urandom(4).hex()}", json.dumps(_CONTENT)),
    )
    sid2 = int(cur2.lastrowid)
    rar_err = FakeRar()
    rar_err.post_prezentare = lambda t, p: (_ for _ in ()).throw(RarError("403", status_code=403))
    w.process_one(conn, settings, rar_err, "tok", {"id": sid2, "account_id": 2, "content": _CONTENT})
    assert len(_events(conn, "submission_error")) == 1
