"""US-003: Reguli text active la ingestie (API + import + corectie web) si la
re-rezolvarea blocajelor (`reresolve_account`).

Verifica ca o regula text salvata in prealabil rezolva o operatie fara mapare
exacta pe TOATE caile de ingestie, in loc sa o lase `needs_mapping`, si ca la
re-rezolvare un rand `needs_mapping` care acum da match pe o regula se deblocheaza.

Codul rezolvat din regula respecta validarea fata de nomenclator (US-002): 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()


@pytest.fixture()
def web_env(monkeypatch):
    """Client web (auth pornit) + get_connection, DB temporara izolata."""
    tmp = tempfile.mkdtemp()
    monkeypatch.setenv("AUTOPASS_DB_PATH", os.path.join(tmp, "rrw.db"))
    monkeypatch.setenv("AUTOPASS_WEB_AUTH_REQUIRED", "true")
    from app.config import get_settings
    get_settings.cache_clear()
    from app.web import ratelimit
    ratelimit._hits.clear()
    from app.db import get_connection
    from app.main import app
    with TestClient(app, follow_redirects=False) as c:
        yield c, get_connection
    ratelimit._hits.clear()
    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 _make_xlsx(rows):
    wb = openpyxl.Workbook()
    ws = wb.active
    ws.title = "Sheet1"
    for row in rows:
        ws.append(row)
    buf = io.BytesIO()
    wb.save(buf)
    return buf.getvalue()


def _row_status_cod(get_connection, sub_id):
    conn = get_connection()
    try:
        r = conn.execute(
            "SELECT status, payload_json FROM submissions WHERE id=?", (sub_id,)
        ).fetchone()
        payload = json.loads(r["payload_json"]) if r["payload_json"] else {}
        cod = (payload.get("prestatii") or [{}])[0].get("cod_prestatie")
        return r["status"], cod
    finally:
        conn.close()


# --------------------------------------------------------------------------- #
# 1. Ingestie API (router.py -> classify_prezentare)                          #
# --------------------------------------------------------------------------- #

def test_ingestie_api_aplica_regula_text(api_env):
    """POST /v1/prezentari cu operatie fara mapare exacta dar match pe regula text
    -> queued (cod din regula), nu needs_mapping."""
    client, get_connection = api_env
    _seed_text_rule(get_connection, 1, "verificare", "OE-2")

    body = {
        "rar_credentials": {"email": "x@y.ro", "password": "s"},
        "prezentari": [{
            "vin": "WVWZZZ1KZAW000123",
            "nr_inmatriculare": "B999TST",
            "data_prestatie": "2026-06-15",
            "odometru_final": "123456",
            "prestatii": [{"cod_op_service": "Verificare frane", "denumire": "Verificare frane"}],
        }],
    }
    r = client.post("/v1/prezentari", json=body)
    assert r.status_code == 200, r.text
    res = r.json()["results"][0]
    assert res["status"] == "queued", res
    assert not res.get("nemapate")

    status, cod = _row_status_cod(get_connection, res["submission_id"])
    assert status == "queued"
    assert cod == "OE-2"


# --------------------------------------------------------------------------- #
# 2. Ingestie import (import_router.py preview + commit)                       #
# --------------------------------------------------------------------------- #

def test_ingestie_import_aplica_regula_text(api_env):
    """Import xlsx cu operatie fara mapare exacta dar match pe regula text:
    preview o marcheaza 'ok' si commit o pune 'queued' (cod din regula)."""
    client, get_connection = api_env
    _seed_text_rule(get_connection, 1, "verificare", "OE-2")

    header = ["VIN", "Nr inmatriculare", "Data prestatie", "Odometru final", "Operatie"]
    row = ["WVWZZZ1KZAW001111", "B100TST", "2026-06-15", "123456", "Verificare frane"]
    data = _make_xlsx([header, row])

    r = client.post(
        "/v1/import",
        files={"file": ("t.xlsx", io.BytesIO(data), "application/octet-stream")},
    )
    assert r.status_code == 200, r.text
    import_id = r.json()["import_id"]

    rc = client.post(f"/v1/import/{import_id}/column-mapping", json={"json_mapare": {
        "VIN": "vin",
        "Nr inmatriculare": "nr_inmatriculare",
        "Data prestatie": "data_prestatie",
        "Odometru final": "odometru_final",
        "Operatie": "operatie",
    }})
    assert rc.status_code == 200, rc.text

    rp = client.get(f"/v1/import/{import_id}/preview")
    assert rp.status_code == 200, rp.text
    assert rp.json()["summary"].get("ok", 0) == 1, rp.json()["summary"]

    rcommit = client.post(f"/v1/import/{import_id}/commit", json={
        "n_confirmat": 1, "reviewed_rows": [],
    })
    assert rcommit.status_code == 200, rcommit.text
    assert rcommit.json()["enqueued"] == 1
    sub_id = rcommit.json()["submissions"][0]["submission_id"]

    status, cod = _row_status_cod(get_connection, sub_id)
    assert status == "queued"
    assert cod == "OE-2"


# --------------------------------------------------------------------------- #
# 3. Corectie web (routes.py -> post_corectie_trimitere)                       #
# --------------------------------------------------------------------------- #

def _create_account_user(get_connection, email, name="Service", password="parolasecreta10"):
    from app.accounts import create_account
    from app.users import create_user
    conn = get_connection()
    try:
        acct_id = create_account(conn, name, active=True)
        create_user(conn, acct_id, email, password)
        return acct_id
    finally:
        conn.close()


def _login(client, email, password="parolasecreta10"):
    resp = client.get("/login")
    m = re.search(r'name="csrf_token"\s+value="([^"]+)"', resp.text)
    assert m
    resp = client.post("/login", data={"email": email, "parola": password, "csrf_token": m.group(1)})
    assert resp.status_code == 303


def _csrf(client):
    resp = client.get("/?tab=acasa")
    m = re.search(r'name="csrf_token"\s+value="([^"]+)"', resp.text)
    assert m
    return m.group(1)


def _insert_needs_mapping(get_connection, acct, op, denumire=None, batch_id=None):
    conn = get_connection()
    try:
        payload = {
            "vin": "WVWZZZ1KZAW000123", "nr_inmatriculare": "B123ABC",
            "data_prestatie": "2026-06-10", "odometru_final": "159004",
            "prestatii": [{"cod_prestatie": None, "cod_op_service": op, "denumire": denumire or op}],
        }
        k = f"k-{os.urandom(6).hex()}"
        cur = conn.execute(
            "INSERT INTO submissions (idempotency_key, account_id, status, payload_json, rar_error, batch_id) "
            "VALUES (?, ?, 'needs_mapping', ?, ?, ?)",
            (k, acct, json.dumps(payload), json.dumps({"unmapped": [{"cod_op_service": op}]}), batch_id),
        )
        conn.commit()
        return int(cur.lastrowid)
    finally:
        conn.close()


def test_corectie_web_aplica_regula_text(web_env):
    """POST /trimitere/{id}/corecteaza pe un needs_mapping a carui operatie acum da
    match pe o regula text -> randul intra 'queued' (cod din regula)."""
    client, get_connection = web_env
    acct = _create_account_user(get_connection, "cor@test.com")
    sid = _insert_needs_mapping(get_connection, acct, op="Verificare frane")
    _seed_text_rule(get_connection, acct, "verificare", "OE-2")

    _login(client, "cor@test.com")
    csrf = _csrf(client)
    resp = client.post(f"/trimitere/{sid}/corecteaza", data={"csrf_token": csrf})
    assert resp.status_code == 200, resp.text

    status, cod = _row_status_cod(get_connection, sid)
    assert status == "queued"
    assert cod == "OE-2"


# --------------------------------------------------------------------------- #
# 4. Re-rezolvare blocaje (mapping.reresolve_account)                          #
# --------------------------------------------------------------------------- #

def test_salvare_regula_rerezolva_blocate(api_env):
    """Dupa salvarea unei reguli noi, reresolve_account deblocheaza randurile
    needs_mapping care acum dau match (acelasi mecanism ca la save_mapping)."""
    client, get_connection = api_env
    sid = _insert_needs_mapping(get_connection, 1, op="Verificare frane")
    _seed_text_rule(get_connection, 1, "verificare", "OE-2")

    from app.mapping import reresolve_account
    conn = get_connection()
    try:
        stats = reresolve_account(conn, 1)
        conn.commit()
    finally:
        conn.close()

    assert stats["requeued"] == 1, stats
    status, cod = _row_status_cod(get_connection, sid)
    assert status == "queued"
    assert cod == "OE-2"
