"""Teste US-002 (PRD 3.4): bara de status persistenta cu etichete umane.

TDD: testele se scriu INAINTE de implementare; la inceput pica (RED),
dupa implementare trec (GREEN).

Rute testate:
- GET /_fragments/status -> bara de status cu etichete umane, scoped pe cont
"""

from __future__ import annotations

import os
import re
import tempfile

import pytest
from starlette.testclient import TestClient


def _create_account_user(email: str = "user@test.com", password: str = "parolasecreta10"):
    """Creeaza cont + user. Intoarce (acct_id, user_id)."""
    from app.accounts import create_account
    from app.users import create_user
    from app.db import get_connection

    conn = get_connection()
    try:
        acct_id = create_account(conn, "Service Test Status", active=True)
        user_id = create_user(conn, acct_id, email, password)
        return acct_id, user_id
    finally:
        conn.close()


def _login(client, email: str, password: str) -> None:
    """Face login real prin HTTP si seteaza cookie-ul de sesiune pe client."""
    resp = client.get("/login")
    assert resp.status_code == 200
    m = re.search(r'name="csrf_token"\s+value="([^"]+)"', resp.text)
    if not m:
        m = re.search(r'value="([^"]+)"\s+name="csrf_token"', resp.text)
    assert m, "csrf_token negasit pe /login"
    csrf = m.group(1)

    resp = client.post("/login", data={
        "email": email,
        "parola": password,
        "csrf_token": csrf,
    })
    assert resp.status_code == 303, f"Login esuat: {resp.status_code} {resp.text[:200]}"


def _insert_submission(status: str, account_id: int) -> None:
    """Insereaza un submission cu status dat pentru un cont dat."""
    from app.db import get_connection
    import json

    conn = get_connection()
    try:
        conn.execute(
            "INSERT INTO submissions (idempotency_key, account_id, status, payload_json) "
            "VALUES (?, ?, ?, ?)",
            (
                f"test-key-{status}-{account_id}-{os.urandom(4).hex()}",
                account_id,
                status,
                json.dumps({"vin": "TEST", "status": status}),
            ),
        )
        conn.commit()
    finally:
        conn.close()


@pytest.fixture()
def client(monkeypatch):
    """Client cu BD izolata si autentificare web activata."""
    tmp = tempfile.mkdtemp()
    monkeypatch.setenv("AUTOPASS_DB_PATH", os.path.join(tmp, "status_test.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()  # izolare: limiterul login e global in-proces
    from app.main import app
    with TestClient(app, follow_redirects=False) as c:
        yield c
    ratelimit._hits.clear()
    get_settings.cache_clear()


# ============================================================
# test_status_fragment_text_uman
# ============================================================

def test_status_fragment_text_uman(client):
    """GET /_fragments/status (autentificat) -> contine text uman de sanatate, NU stari tehnice brute.

    Actualizat US-003 (PRD 5.15): strip sanatate unificat in loc de bife individuale worker/RAR.
    Textul 'Trimitere automata' a fost inlocuit cu 'declaratiile curg normal' / 'Blocat: ...'.
    """
    _create_account_user("status@test.com", "parolasecreta10")
    _login(client, "status@test.com", "parolasecreta10")

    resp = client.get("/_fragments/status")
    assert resp.status_code == 200

    html = resp.text
    # US-003 D6: strip sanatate cu text uman compus (nu bife individuale)
    assert "declaratiile" in html.lower(), (
        f"Fragmentul nu contine textul de sanatate ('declaratiile'). HTML (primele 500 ch): {html[:500]}"
    )
    # NU trebuie sa contina text tehnic brut
    assert "worker viu" not in html.lower(), (
        f"Fragmentul contine 'worker viu' (text tehnic brut). HTML (primele 500 ch): {html[:500]}"
    )
    assert "viu</div>" not in html, (
        "Fragmentul contine eticheta bruta 'viu'"
    )


# ============================================================
# test_status_blocate_defalcare
# ============================================================

def test_status_blocate_defalcare(client):
    """Cu submissions blocate in DB, fragmentul arata defalcarea pe motiv (texte umane)."""
    acct_id, _ = _create_account_user("blocate@test.com", "parolasecreta10")
    _login(client, "blocate@test.com", "parolasecreta10")

    # Insereaza submissions blocate din fiecare tip
    _insert_submission("needs_mapping", acct_id)
    _insert_submission("needs_mapping", acct_id)
    _insert_submission("needs_data", acct_id)
    _insert_submission("error", acct_id)

    # Pill-urile s-au mutat in bara de filtre din sectiunea Trimiteri (nu in bara de status).
    resp = client.get("/?tab=acasa")
    assert resp.status_code == 200
    html = resp.text
    # Pill-urile au etichetele scurte per categorie (nu etichetele lungi din eticheta_stare)
    assert "Lipsa cod" in html, "Acasa nu arata pill-ul pentru needs_mapping"
    assert "Date incomplete" in html, "Acasa nu arata pill-ul pentru needs_data"
    assert "Eroare" in html, "Acasa nu arata pill-ul pentru error"
    # Pill-urile arata numarul total per categorie (2 needs_mapping, 1 needs_data, 1 error)
    assert 'class="pill-cat"' in html, "Pill-urile trebuie sa fie elemente cu clasa pill-cat"
    assert "<button" in html, "Pill-urile trebuie sa fie elemente <button>"


# ============================================================
# test_status_se_reincarca_htmx
# ============================================================

def test_status_se_reincarca_htmx(client):
    """Fragmentul contine atribut hx-trigger cu poll periodic (every 15s)."""
    _create_account_user("htmx@test.com", "parolasecreta10")
    _login(client, "htmx@test.com", "parolasecreta10")

    resp = client.get("/_fragments/status")
    assert resp.status_code == 200

    html = resp.text
    # Trebuie sa contina hx-trigger periodic
    assert "hx-trigger" in html, (
        f"Fragmentul nu contine atribut hx-trigger. HTML: {html[:500]}"
    )
    assert "every 15s" in html, (
        f"Fragmentul nu contine poll 'every 15s'. HTML: {html[:500]}"
    )
    # Trebuie sa aiba endpoint corect pentru auto-refresh
    assert "/_fragments/status" in html, (
        "Fragmentul nu contine referinta la /_fragments/status pentru hx-get"
    )
    # Trebuie sa aiba un id stabil pe containerul radacina
    assert 'id="status-bar"' in html, (
        "Fragmentul nu are id='status-bar' pe containerul radacina"
    )


# ============================================================
# US-014: banner "Necesita atentia ta" actionabil
# ============================================================

def _insert_submission_vehicul(status, account_id, vin, nr):
    from app.db import get_connection
    import json
    conn = get_connection()
    try:
        conn.execute(
            "INSERT INTO submissions (idempotency_key, account_id, status, payload_json) VALUES (?, ?, ?, ?)",
            (f"k-{os.urandom(5).hex()}", account_id, status,
             json.dumps({"vin": vin, "nr_inmatriculare": nr, "data_prestatie": "2026-06-15",
                         "odometru_final": "1", "prestatii": [{"cod_prestatie": "OE-1"}]})),
        )
        conn.commit()
    finally:
        conn.close()


def test_categorie_blocata_linkeaza_la_trimiteri_filtrate(client):
    """Pill-ul error filtreaza tabelul prin filtreazaStare(this, 'error') in bara de filtre."""
    acct_id, _ = _create_account_user("link@test.com", "parolasecreta10")
    _login(client, "link@test.com", "parolasecreta10")
    _insert_submission("error", acct_id)

    html = client.get("/?tab=acasa").text
    # Pill-ul scrie campul de filtru si re-trimite form-ul (nu mai navigheaza prin deep-link)
    assert "filtreazaStare(this, 'error')" in html
    assert 'data-status="error"' in html
    assert "tab=acasa&status=error" not in html


def test_status_nu_arata_identificator_rand_blocat(client):
    """US-003 (PRD 5.10): VIN/nr inmatriculare nu mai apar in bara de status.
    Lista de ID-uri a fost inlocuita cu pill-uri cu numar total (fara PII nominal)."""
    acct_id, _ = _create_account_user("ident@test.com", "parolasecreta10")
    _login(client, "ident@test.com", "parolasecreta10")
    _insert_submission_vehicul("error", acct_id, "WVWZZZ1KZAW000123", "B123ABC")

    html = client.get("/_fragments/status").text
    # Bara de status arata doar contoare, nu lista cu VIN/nr per rand (fara PII nominal)
    assert "B123ABC" not in html, "Nr inmatriculare nu trebuie sa mai apara in bara de status"
    assert "WVWZZZ1KZAW000123" not in html, "VIN integral nu trebuie expus"
    assert "0123" not in html, "VIN partial nu trebuie sa mai apara in bara de status"


def test_scoped_pe_cont(client):
    from app.accounts import create_account
    from app.db import get_connection
    acct_id, _ = _create_account_user("own@test.com", "parolasecreta10")
    conn = get_connection()
    try:
        other = create_account(conn, "Alt", active=True)
    finally:
        conn.close()
    _login(client, "own@test.com", "parolasecreta10")
    _insert_submission_vehicul("error", other, "OTHERVIN000009999", "X999ZZZ")

    html = client.get("/_fragments/status").text
    # randul altui cont NU apare in banner-ul meu
    assert "X999ZZZ" not in html
    assert "9999" not in html
