"""US-010: Telemetrie hit regula text in `app_events`.

Cand o operatie nemapata primeste cod RAR dintr-o regula text (substring), apelantii
cu `conn` (ingestie API, import, re-rezolvare) emit un eveniment `text_rule_hit` in
`app_events` cu {submission_id, account_id, pattern, cod_prestatie}. Maparea exacta
(cod_op_service -> cod_prestatie) NU emite acest eveniment. Evenimentul e redactat
(fara PII) si scoped pe cont.

Folosim `OE-2`, cod valid din seed-ul nomenclatorului.
"""

from __future__ import annotations

import io
import json
import os
import re
import tempfile

import openpyxl
import pytest
from fastapi.testclient import TestClient


# --------------------------------------------------------------------------- #
# Fixtures                                                                     #
# --------------------------------------------------------------------------- #

@pytest.fixture()
def api_env(monkeypatch):
    """Client API + get_connection, DB temporara izolata (fara web-auth)."""
    tmp = tempfile.mkdtemp()
    monkeypatch.setenv("AUTOPASS_DB_PATH", os.path.join(tmp, "rr.db"))
    from app.config import get_settings
    get_settings.cache_clear()
    from app.db import get_connection
    from app.main import app
    with TestClient(app) as c:
        yield c, get_connection
    get_settings.cache_clear()


# --------------------------------------------------------------------------- #
# Helpere                                                                      #
# --------------------------------------------------------------------------- #

def _seed_text_rule(get_connection, account_id, pattern, cod, auto_send=True):
    from app.mapping import save_text_rule
    conn = get_connection()
    try:
        save_text_rule(conn, account_id, pattern, cod, auto_send=auto_send)
        conn.commit()
    finally:
        conn.close()


def _seed_mapping(get_connection, account_id, op, cod, auto_send=True):
    from app.mapping import save_mapping
    conn = get_connection()
    try:
        save_mapping(conn, account_id, op, cod, auto_send=auto_send)
        conn.commit()
    finally:
        conn.close()


def _text_rule_hits(get_connection):
    conn = get_connection()
    try:
        rows = conn.execute(
            "SELECT account_id, context_json FROM app_events WHERE tip='text_rule_hit' ORDER BY id"
        ).fetchall()
        return [dict(r) for r in rows]
    finally:
        conn.close()


_VIN = "WVWZZZ1KZAW000123"


def _post_prezentare(client, op, denumire=None):
    body = {
        "rar_credentials": {"email": "x@y.ro", "password": "parola-secreta"},
        "prezentari": [{
            "vin": _VIN,
            "nr_inmatriculare": "B999TST",
            "data_prestatie": "2026-06-15",
            "odometru_final": "123456",
            "prestatii": [{"cod_op_service": op, "denumire": denumire or op}],
        }],
    }
    return client.post("/v1/prezentari", json=body)


# --------------------------------------------------------------------------- #
# 1. Hit regula -> eveniment                                                   #
# --------------------------------------------------------------------------- #

def test_hit_regula_emite_app_event(api_env):
    """O operatie rezolvata prin regula text emite `text_rule_hit` cu pattern + cod."""
    client, get_connection = api_env
    _seed_text_rule(get_connection, 1, "verificare", "OE-2")

    r = _post_prezentare(client, "Verificare frane")
    assert r.status_code == 200, r.text
    res = r.json()["results"][0]
    assert res["status"] == "queued", res
    sub_id = res["submission_id"]

    hits = _text_rule_hits(get_connection)
    assert len(hits) == 1, hits
    ctx = json.loads(hits[0]["context_json"])
    assert ctx["submission_id"] == sub_id
    assert ctx["account_id"] == 1
    assert ctx["pattern"] == "verificare"
    assert ctx["cod_prestatie"] == "OE-2"


# --------------------------------------------------------------------------- #
# 2. Maparea exacta NU emite                                                   #
# --------------------------------------------------------------------------- #

def test_mapare_exacta_nu_emite_text_rule_hit(api_env):
    """O operatie rezolvata prin mapare exacta (cod_op_service) nu emite text_rule_hit."""
    client, get_connection = api_env
    _seed_mapping(get_connection, 1, "Verificare frane", "OE-2")

    r = _post_prezentare(client, "Verificare frane")
    assert r.status_code == 200, r.text
    res = r.json()["results"][0]
    assert res["status"] == "queued", res

    hits = _text_rule_hits(get_connection)
    assert hits == [], hits


# --------------------------------------------------------------------------- #
# 3. Eveniment redactat + scoped pe cont                                       #
# --------------------------------------------------------------------------- #

def test_event_redactat_si_scoped_pe_cont(api_env):
    """Evenimentul e scoped pe cont (coloana account_id) si nu contine PII (VIN integral)."""
    client, get_connection = api_env
    _seed_text_rule(get_connection, 1, "verificare", "OE-2")

    r = _post_prezentare(client, "Verificare frane")
    assert r.status_code == 200, r.text

    hits = _text_rule_hits(get_connection)
    assert len(hits) == 1, hits
    assert hits[0]["account_id"] == 1
    # Fara PII: VIN-ul integral nu apare in context.
    assert _VIN not in (hits[0]["context_json"] or "")


# --------------------------------------------------------------------------- #
# 4. Calea web import commit (routes.py -> web_confirma_import)                #
# --------------------------------------------------------------------------- #

@pytest.fixture()
def web_env(monkeypatch):
    """Client web (mod dev) + get_connection + cont creat; require_login fixat pe cont."""
    tmp = tempfile.mkdtemp()
    monkeypatch.setenv("AUTOPASS_DB_PATH", os.path.join(tmp, "rrw.db"))
    monkeypatch.setenv("AUTOPASS_WEB_AUTH_REQUIRED", "false")
    from app.config import get_settings
    get_settings.cache_clear()
    from app.web import ratelimit
    ratelimit._hits.clear()
    from app.accounts import create_account
    from app.db import get_connection
    from app.main import app
    with TestClient(app, follow_redirects=False) as c:
        conn = get_connection()
        acct = create_account(conn, "Cont Web Telemetrie", active=True)
        conn.commit()
        conn.close()
        monkeypatch.setattr("app.web.routes.require_login", lambda r: acct)
        yield c, get_connection, acct
    ratelimit._hits.clear()
    get_settings.cache_clear()


def _make_xlsx(rows):
    wb = openpyxl.Workbook()
    ws = wb.active
    if rows:
        ws.append(list(rows[0].keys()))
        for r in rows:
            ws.append(list(r.values()))
    buf = io.BytesIO()
    wb.save(buf)
    return buf.getvalue()


def _csrf_from(html):
    m = re.search(r'name="csrf_token" value="([^"]*)"', html)
    return m.group(1) if m else ""


def test_web_import_commit_emite_text_rule_hit(web_env):
    """Import web commit pe un rand a carui operatie da match pe o regula text
    emite `text_rule_hit` in app_events cu submission_id-ul randului creat."""
    client, get_connection, acct = web_env
    _seed_text_rule(get_connection, acct, "verificare", "OE-2")

    rows = [{
        "vin": "WVWZZZ1KZAW001111", "nr_inmatriculare": "B100TST",
        "data_prestatie": "2026-06-15", "odometru_final": "123456",
        "operatie": "Verificare frane",
    }]
    r_up = client.post(
        "/_import/upload",
        files={"file": ("t.xlsx", _make_xlsx(rows),
                        "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")},
    )
    assert r_up.status_code == 200, r_up.text
    csrf = _csrf_from(r_up.text)
    batch_id = int(re.search(r"/_import/(\d+)/mapare-coloane", r_up.text).group(1))

    r_map = client.post(
        f"/_import/{batch_id}/mapare-coloane",
        data={
            "csrf_token": csrf,
            "colname": ["vin", "nr_inmatriculare", "data_prestatie", "odometru_final", "operatie"],
            "canon": ["vin", "nr_inmatriculare", "data_prestatie", "odometru_final", "operatie"],
        },
    )
    assert r_map.status_code == 200, r_map.text
    csrf = _csrf_from(r_map.text) or csrf

    r_commit = client.post(f"/_import/{batch_id}/confirma", data={"n_confirmat": "1", "csrf_token": csrf})
    assert r_commit.status_code == 200, r_commit.text

    conn = get_connection()
    try:
        sub = conn.execute(
            "SELECT id, status FROM submissions WHERE account_id=? AND batch_id=?", (acct, batch_id)
        ).fetchone()
    finally:
        conn.close()
    assert sub is not None, "submission-ul nu a fost creat"
    assert sub["status"] == "queued"

    hits = _text_rule_hits(get_connection)
    assert len(hits) == 1, hits
    ctx = json.loads(hits[0]["context_json"])
    assert ctx["submission_id"] == sub["id"]
    assert ctx["account_id"] == acct
    assert ctx["pattern"] == "verificare"
    assert ctx["cod_prestatie"] == "OE-2"
