"""Teste US-003 (PRD 5.15): strip sanatate mereu-vizibil + carduri-contor pe dashboard.

D6 (strip sanatate): linie colorata DEASUPRA contoarelor — verde "declaratiile curg" /
  rosu "Blocat: worker oprit / RAR inaccesibil", cu glifa accesibila (✓/✗).
D4 (contoare): In coada / Trimise (all-time + luna/azi) / De corectat.
E7 (timezone): azi/luna bucketate in timp local RO (UTC+3), nu UTC.

Actualizat in US-003 (PRD 5.15): bara veche cu bife individuale worker/RAR
inlocuita de strip unificat de sanatate + carduri-contor.
"""

from __future__ import annotations

import json
import os
import re
import tempfile
from datetime import datetime, timedelta, timezone

import pytest
from starlette.testclient import TestClient


def _create_account_user(email: str, password: str = "parolasecreta10"):
    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 Bife", 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:
    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"
    resp = client.post("/login", data={"email": email, "parola": password, "csrf_token": m.group(1)})
    assert resp.status_code == 303, f"Login esuat: {resp.status_code} {resp.text[:200]}"


def _set_heartbeat(last_beat: str | None, last_rar_login_ok: str | None) -> None:
    from app.db import get_connection

    conn = get_connection()
    try:
        conn.execute(
            "UPDATE worker_heartbeat SET last_beat=?, last_rar_login_ok=? WHERE id=1",
            (last_beat, last_rar_login_ok),
        )
        conn.commit()
    finally:
        conn.close()


@pytest.fixture()
def client(monkeypatch):
    tmp = tempfile.mkdtemp()
    monkeypatch.setenv("AUTOPASS_DB_PATH", os.path.join(tmp, "bife_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()
    from app.main import app
    with TestClient(app, follow_redirects=False) as c:
        yield c
    ratelimit._hits.clear()
    get_settings.cache_clear()


# ---------------------------------------------------------------------------
# Teste existente — actualizate pentru US-003 D6 (strip unificat in loc de bife individuale)
# ---------------------------------------------------------------------------

def test_status_are_bife_verzi_cand_totul_ok(client):
    """US-003 PRD 5.16: worker viu + RAR login recent -> strip-sanatate in DOM dar ASCUNS (hidden).
    Banda rosie apare DOAR cand BLOCAT. Starea OK e indicata de dot-ul verde din antet (base.html).
    Elementul id=strip-sanatate ramane in DOM pentru compatibilitate (nu dispare complet).
    """
    _create_account_user("bifeok@test.com")
    _login(client, "bifeok@test.com", "parolasecreta10")

    now = datetime.now(timezone.utc).isoformat()
    _set_heartbeat(last_beat=now, last_rar_login_ok=now)

    resp = client.get("/_fragments/status")
    assert resp.status_code == 200
    html = resp.text
    # US-003: elementul strip-sanatate e prezent in DOM dar ascuns cand totul e ok
    assert 'id="strip-sanatate"' in html, f"id=strip-sanatate lipseste complet din fragment. HTML: {html[:600]}"
    # Cand OK, banda nu trebuie sa afiseze ✗ (eroare) — ✓ nu mai apare (banda e ascunsa)
    assert "&#10007;" not in html, \
        f"Glifa ✗ (eroare) apare cand starea e ok — banda e gresit afisata. HTML: {html[:600]}"


def test_status_are_bife_rosii_cand_worker_oprit(client):
    """Fara heartbeat -> worker oprit -> glifa rosie ✗ + text explicit 'blocat' / 'nu pleaca'."""
    _create_account_user("biferosu@test.com")
    _login(client, "biferosu@test.com", "parolasecreta10")

    _set_heartbeat(last_beat=None, last_rar_login_ok=None)

    resp = client.get("/_fragments/status")
    assert resp.status_code == 200
    html = resp.text
    assert "&#10007;" in html, f"Lipseste glifa ✗ cand worker oprit. HTML: {html[:600]}"
    # US-003 D6: mesaj explicit (nu text vag "oprita")
    assert "blocat" in html.lower(), f"Cuvantul 'blocat' lipseste la worker oprit. HTML: {html[:600]}"
    assert "nu pleaca" in html.lower(), f"Avertismentul 'nu pleaca' lipseste. HTML: {html[:600]}"


def test_status_data_formatata_romaneste(client):
    """Ultima autentificare RAR apare ca dd.mm.yyyy hh24:mi:ss."""
    _create_account_user("bifedata@test.com")
    _login(client, "bifedata@test.com", "parolasecreta10")

    now = datetime.now(timezone.utc).isoformat()
    _set_heartbeat(last_beat=now, last_rar_login_ok="2026-06-18T14:30:22")

    resp = client.get("/_fragments/status")
    assert resp.status_code == 200
    assert "18.06.2026 14:30:22" in resp.text, (
        f"Data nu e formatata romaneste. HTML: {resp.text[:800]}"
    )


def test_status_fara_fonturi_minuscule(client):
    """Niciun text din bara nu mai foloseste font-size literal sub 13px (US-001 AC)."""
    _create_account_user("bifefont@test.com")
    _login(client, "bifefont@test.com", "parolasecreta10")

    resp = client.get("/_fragments/status")
    assert resp.status_code == 200
    html = resp.text
    # Culorile prin clase CSS (nu inline font-size); shorthand font:N Xpx nu e acoperit de aceste litere
    for bad in ("font-size:11px", "font-size:12px", "font-size: 11px", "font-size: 12px"):
        assert bad not in html, f"Bara de status foloseste {bad} (sub 13px) inline."


# ---------------------------------------------------------------------------
# Teste NOI pentru US-003 (RED inainte de implementare)
# ---------------------------------------------------------------------------

def test_strip_sanatate_mereu_vizibil(client):
    """D6: strip de sanatate e prezent in fragment, indiferent de starea worker/RAR."""
    _create_account_user("stripviz@test.com")
    _login(client, "stripviz@test.com", "parolasecreta10")

    # Stare worker viu
    now = datetime.now(timezone.utc).isoformat()
    _set_heartbeat(last_beat=now, last_rar_login_ok=now)

    resp = client.get("/_fragments/status")
    assert resp.status_code == 200
    html = resp.text
    assert 'id="strip-sanatate"' in html, (
        f"Strip sanatate (id='strip-sanatate') lipseste din fragment. HTML: {html[:600]}"
    )


def test_strip_rosu_worker_oprit(client):
    """D6: worker oprit → strip rosu cu glifа ✗ + text 'Blocat: worker oprit — declaratiile NU pleaca'."""
    _create_account_user("stroprosu@test.com")
    _login(client, "stroprosu@test.com", "parolasecreta10")

    _set_heartbeat(last_beat=None, last_rar_login_ok=None)

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

    assert 'id="strip-sanatate"' in html, "Strip sanatate lipseste."
    assert "&#10007;" in html, "Glifa ✗ lipseste in strip rosu."
    assert "blocat" in html.lower(), "Cuvantul 'Blocat' trebuie sa apara cand worker e oprit."
    assert "worker oprit" in html.lower(), "Textul 'worker oprit' trebuie sa fie explicit in strip."
    assert "nu pleaca" in html.lower(), "Avertismentul 'NU pleaca' trebuie sa fie in strip."


def test_trei_contoare_card(client):
    """US-002 PRD 5.16: fragment status contine 5 carduri .contor-card separate:
    Total / Luna asta / Azi / In coada / De corectat."""
    _create_account_user("treicont@test.com")
    _login(client, "treicont@test.com", "parolasecreta10")

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

    count = html.count("contor-card")
    assert count >= 5, (
        f"Trebuie minim 5 elemente contor-card (US-002 PRD 5.16: Total/Luna/Azi/Coada/Corectat), "
        f"gasit: {count}. HTML: {html[:800]}"
    )
    # Etichete asteptate (US-002 PRD 5.16: 5 carduri separate)
    assert "Total" in html, "Eticheta 'Total' lipseste din contoare (US-002 PRD 5.16)."
    assert "Luna asta" in html, "Eticheta 'Luna asta' lipseste din contoare (US-002 PRD 5.16)."
    assert "Azi" in html, "Eticheta 'Azi' lipseste din contoare (US-002 PRD 5.16)."
    assert "In coada" in html, "Eticheta 'In coada' lipseste din contoare."
    assert "De corectat" in html, "Eticheta 'De corectat' lipseste din contoare."


def test_trimise_all_time_luna_azi(client):
    """D4: cardul Trimise afiseaza all-time ca cifra principala + sub-linie 'luna N · azi N'."""
    acct_id, _ = _create_account_user("trimisetime@test.com")
    _login(client, "trimisetime@test.com", "parolasecreta10")

    # Insereaza o trimitere sent cu updated_at = acum
    from app.db import get_connection
    conn = get_connection()
    try:
        conn.execute(
            "INSERT INTO submissions (account_id, status, payload_json, idempotency_key, updated_at) "
            "VALUES (?, 'sent', ?, 'key-luna-azi', datetime('now'))",
            (acct_id, json.dumps({"vin": "VINTEST00000000001"})),
        )
        conn.commit()
    finally:
        conn.close()

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

    # Sub-linia trebuie sa contina "luna" si "azi" (format: "luna N · azi N")
    assert "luna" in html.lower(), (
        f"Sub-linia 'luna N · azi N' lipseste din cardul Trimise. HTML: {html[:800]}"
    )
    assert "azi" in html.lower(), (
        f"Sub-linia 'luna N · azi N' nu contine 'azi'. HTML: {html[:800]}"
    )


def test_fara_bara_veche(client):
    """US-003: contoarele vechi inline ('In asteptare:' / 'Declarate la RAR:') nu mai apar."""
    _create_account_user("faraveche@test.com")
    _login(client, "faraveche@test.com", "parolasecreta10")

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

    # Stilul vechi: etichete inline cu colon (bara de la PRD 3.5)
    assert "In asteptare:" not in html, (
        f"Contorul vechi 'In asteptare:' inca prezent. HTML: {html[:600]}"
    )
    assert "Declarate la RAR:" not in html, (
        f"Contorul vechi 'Declarate la RAR:' inca prezent. HTML: {html[:600]}"
    )


def test_banda_apare_doar_cand_blocat(client):
    """US-003 (PRD 5.16): banda rosie completa apare NUMAI cand BLOCAT.
    Cand totul e ok, strip-sanatate are atributul 'hidden' (ascuns, nu disparut).
    Cand worker e oprit, strip-sanatate NU are 'hidden' (e vizibil, rosu).
    """
    _create_account_user("bandablocat@test.com")
    _login(client, "bandablocat@test.com", "parolasecreta10")

    # Stare OK: strip ascuns
    now = datetime.now(timezone.utc).isoformat()
    _set_heartbeat(last_beat=now, last_rar_login_ok=now)
    resp = client.get("/_fragments/status")
    assert resp.status_code == 200
    html_ok = resp.text
    # Cand OK, elementul e ascuns
    assert 'id="strip-sanatate"' in html_ok, "strip-sanatate lipseste din DOM cand totul e ok"
    assert "&#10007;" not in html_ok, "Glifa eroare apare cand sanatate=ok (banda nu trebuie sa fie rosie)"

    # Stare BLOCAT: strip vizibil cu glifa ✗
    _set_heartbeat(last_beat=None, last_rar_login_ok=None)
    resp = client.get("/_fragments/status")
    assert resp.status_code == 200
    html_err = resp.text
    assert 'id="strip-sanatate"' in html_err, "strip-sanatate lipseste din DOM cand blocat"
    assert "&#10007;" in html_err, "Glifa ✗ lipseste cand BLOCAT (banda trebuie sa fie rosie)"


def test_rar_dot_in_antet_ok(client):
    """US-003 (PRD 5.16): cand logat si sanatate_ok, antetul contine chip-ul RAR cu clasa rar-ok.
    Starea ok se vede din header (dot verde pulsant), nu din banda de stare (care e ascunsa).
    """
    _create_account_user("rardot@test.com")
    _login(client, "rardot@test.com", "parolasecreta10")

    now = datetime.now(timezone.utc).isoformat()
    _set_heartbeat(last_beat=now, last_rar_login_ok=now)

    resp = client.get("/", follow_redirects=True)
    assert resp.status_code == 200
    html = resp.text
    # Chip RAR in antet (nu in banda de stare)
    assert "rar-chip" in html, "Clasa rar-chip lipseste din HTML (dot RAR in antet, US-003)"
    assert "rar-ok" in html, "Clasa rar-ok lipseste — dot verde cand sanatate ok (US-003)"
    assert "rar-dot" in html, "Clasa rar-dot lipseste din chip (US-003)"


def test_rar_in_meniu_burger(client):
    """US-003/010 (PRD 5.16): meniul burger contine starea RAR ca prima intrare (RAR online / RAR indisponibil)."""
    _create_account_user("rarmeniu@test.com")
    _login(client, "rarmeniu@test.com", "parolasecreta10")

    now = datetime.now(timezone.utc).isoformat()
    _set_heartbeat(last_beat=now, last_rar_login_ok=now)

    resp = client.get("/", follow_redirects=True)
    assert resp.status_code == 200
    html = resp.text
    # Meniul burger (cont-menu) contine indicatorul RAR
    assert "cont-menu" in html, "Meniu burger (cont-menu) lipseste din HTML"
    assert "RAR online" in html or "RAR indisponibil" in html, \
        "Starea RAR nu apare in meniu burger (US-003/010)"
    # Prima intrare e starea RAR — prezenta class menu-rar-line
    assert "menu-rar-line" in html, "Clasa menu-rar-line lipseste din burger (US-003)"


def test_anuleaza_are_data_modal_close(client):
    """US-007 (PRD 5.16): overlay-ul modal si butonul de inchidere au atributul data-modal-close."""
    # Butonul si overlay-ul trebuie sa aiba data-modal-close pentru ca handler-ul cu .closest() sa functioneze
    # Verificam in baza template-ului base.html (modal e definit acolo, randat pe toate paginile)
    # Testam pe dashboard dupa login (unde baza e incarcata)
    _create_account_user("modalclose@test.com")
    _login(client, "modalclose@test.com", "parolasecreta10")
    resp = client.get("/", follow_redirects=True)
    assert resp.status_code == 200
    html = resp.text
    assert "data-modal-close" in html, \
        "data-modal-close lipseste din template — modalul nu se poate inchide (US-007)"


def test_modal_close_pe_element_interior(client):
    """US-007 (PRD 5.16): handler-ul modal foloseste .closest('[data-modal-close]') nu
    .hasAttribute directe — astfel click pe un element interior al backdrop-ului functioneaza."""
    _create_account_user("modalclosest@test.com")
    _login(client, "modalclosest@test.com", "parolasecreta10")
    resp = client.get("/", follow_redirects=True)
    assert resp.status_code == 200
    html = resp.text
    # Verificam ca JS-ul foloseste closest, nu hasAttribute
    assert "closest('[data-modal-close]')" in html, \
        "Handler-ul modal foloseste hasAttribute in loc de closest (US-007) — click pe copil nu va inchide modalul"


def _set_tz_bucuresti(monkeypatch, request):
    """Forteaza TZ=Europe/Bucharest pentru ca modificatorul SQLite 'localtime' sa
    rezolve la fusul RO indiferent de TZ-ul runner-ului (CI ruleaza de regula in UTC).
    Restaureaza tzset-ul la teardown (monkeypatch reface env-ul TZ; tzset reciteste)."""
    import time
    monkeypatch.setenv("TZ", "Europe/Bucharest")
    if hasattr(time, "tzset"):
        time.tzset()
        request.addfinalizer(time.tzset)  # dupa ce monkeypatch reface TZ -> reciteste


def test_granita_miez_noapte_local_ro(monkeypatch, request):
    """E7: trimitere cu updated_at = ieri UTC 22:00 = azi Romania (UTC+2/+3) se numara 'azi'.

    Cu date(updated_at) simplu (UTC) ar aparea pe ziua precedenta — GRESIT.
    Cu date(updated_at, 'localtime') + TZ=Europe/Bucharest apare pe ziua de azi RO — CORECT
    (DST-aware: +2h iarna, +3h vara).
    """
    _set_tz_bucuresti(monkeypatch, request)
    tmp = tempfile.mkdtemp()
    monkeypatch.setenv("AUTOPASS_DB_PATH", os.path.join(tmp, "granita.db"))
    from app.config import get_settings
    get_settings.cache_clear()

    from app.db import get_connection, init_db
    from app.accounts import create_account
    from app.web.routes import _status_counts

    # Initializeaza schema (init_db o face idempotent)
    init_db()

    # Construim un timestamp care, stocat ca UTC, cade pe ziua PRECEDENTA in UTC dar pe
    # ACEEASI zi RO ca 'now'. 00:30 RO local e mereu ziua UTC precedenta (UTC+2 iarna /
    # UTC+3 vara -> 22:30 / 21:30 UTC), DST-aware. Ancorat pe RO-now (nu pe data UTC),
    # deci robust la orice ora de rulare. Bug vechi: boundary ancorat pe today_utc pica
    # in fereastra de dupa miezul noptii RO, cand date('now','localtime') e deja ziua
    # urmatoare fata de today_utc -> sent_today=0 fals.
    from zoneinfo import ZoneInfo

    now_ro = datetime.now(ZoneInfo("Europe/Bucharest"))
    ro_devreme = now_ro.replace(hour=0, minute=30, second=0, microsecond=0)
    boundary_updated_at = ro_devreme.astimezone(timezone.utc).strftime("%Y-%m-%d %H:%M:%S")

    conn = get_connection()
    try:
        acct_id = create_account(conn, "Service Granita", active=True)
        conn.execute(
            "INSERT INTO submissions (account_id, status, payload_json, idempotency_key, updated_at) "
            "VALUES (?, 'sent', ?, 'key-granita-1', ?)",
            (acct_id, json.dumps({"vin": "VIN00000000000001"}), boundary_updated_at),
        )
        conn.commit()

        counts = _status_counts(conn, acct_id)

        # 22:00 UTC -> azi in RO (localtime) => sent_today=1
        assert counts["sent_today"] == 1, (
            f"E7 FAIL: trimitere la {boundary_updated_at} UTC = azi in Romania "
            f"trebuie sa fie 'azi', dar sent_today={counts.get('sent_today')}. "
            "SQL trebuie sa foloseasca date(updated_at, 'localtime') = date('now', 'localtime')."
        )
        assert counts["sent_month"] >= 1, (
            f"E7: sent_month trebuie sa fie >= 1, got {counts.get('sent_month')}"
        )
    finally:
        conn.close()
    get_settings.cache_clear()


def test_iarna_nu_bleed_in_ziua_urmatoare(monkeypatch, request):
    """Bug fix (code-review 5.15): iarna (UTC+2), o trimitere la 21:30 UTC = 23:30 RO AZI
    NU trebuie sa cada pe ziua de MAINE.

    Vechiul offset fix '+3 hours' o impingea la 00:30 maine -> sent_today gresit.
    'localtime' (DST-aware) o pastreaza corect pe azi. Testul fixeaza o data de iarna
    explicita (15 ianuarie) ca sa fie determinist indiferent de cand ruleaza.
    """
    _set_tz_bucuresti(monkeypatch, request)
    tmp = tempfile.mkdtemp()
    monkeypatch.setenv("AUTOPASS_DB_PATH", os.path.join(tmp, "iarna.db"))
    from app.config import get_settings
    get_settings.cache_clear()

    from app.db import get_connection, init_db
    from app.accounts import create_account

    init_db()

    # Data de iarna fixa: 2026-01-15. 21:30 UTC = 23:30 RO (EET, UTC+2) -> ziua 15, nu 16.
    conn = get_connection()
    try:
        acct_id = create_account(conn, "Service Iarna", active=True)
        conn.execute(
            "INSERT INTO submissions (account_id, status, payload_json, idempotency_key, updated_at) "
            "VALUES (?, 'sent', ?, 'key-iarna-1', ?)",
            (acct_id, json.dumps({"vin": "VIN00000000000002"}), "2026-01-15 21:30:00"),
        )
        conn.commit()

        # Verifica direct ce zi RO atribuie SQLite (localtime vs vechiul +3h).
        row = conn.execute(
            "SELECT date(updated_at, 'localtime') AS zi_local, "
            "       date(updated_at, '+3 hours') AS zi_plus3 "
            "FROM submissions WHERE idempotency_key='key-iarna-1'"
        ).fetchone()
        assert row["zi_local"] == "2026-01-15", (
            f"localtime (EET, UTC+2) trebuie sa pastreze 21:30 UTC pe 15 ian RO, "
            f"got {row['zi_local']}"
        )
        # Demonstreaza bug-ul vechi: +3h impingea pe 16 ian (ziua gresita iarna).
        assert row["zi_plus3"] == "2026-01-16", (
            f"Confirmare bug vechi: '+3 hours' iarna pune 21:30 UTC pe 16 ian, got {row['zi_plus3']}"
        )
    finally:
        conn.close()
    get_settings.cache_clear()


# ===========================================================================
# US-006 (PRD 5.17) — Afisaj plan curent: trial / consum / warn / banner
# ===========================================================================

def _set_trial_until(account_id: int, trial_until_str: str | None) -> None:
    """Seteaza direct trial_until pentru un cont (helper de test)."""
    from app.db import get_connection
    conn = get_connection()
    try:
        conn.execute(
            "UPDATE accounts SET trial_until=? WHERE id=?",
            (trial_until_str, account_id),
        )
        conn.commit()
    finally:
        conn.close()


def _insert_submissions_sent(account_id: int, n: int) -> None:
    """Insereaza N submissions sent in luna curenta (helper de test)."""
    from app.db import get_connection
    import json as _json
    conn = get_connection()
    try:
        for i in range(n):
            conn.execute(
                "INSERT INTO submissions (account_id, status, payload_json, idempotency_key, created_at) "
                "VALUES (?, 'sent', ?, ?, datetime('now'))",
                (account_id, _json.dumps({"vin": f"VIN{i:013d}"}), f"key-plan-{account_id}-{i}"),
            )
        conn.commit()
    finally:
        conn.close()


def test_afisaj_plan_si_zile_trial(client):
    """US-006 + T-6 (5.16): cont in trial Pro -> linia de plan din meniul burger (pagina
    completa) arata 'Plan: Pro · trial N zile ramase'. In starea normala (non-warn) plan_linie
    NU mai e rand in corpul fragmentului status — traieste in badge antet + burger.
    Contul nou primeste trial_until=now+30z automat la creare.
    """
    acct_id, _ = _create_account_user("trialzile@test.com")
    _login(client, "trialzile@test.com", "parolasecreta10")

    # trial_until = now + 18 zile + 12h (buffer pt a evita delta.days=17 din timing test)
    future = (datetime.now(timezone.utc) + timedelta(days=18, hours=12)).strftime("%Y-%m-%d %H:%M:%S")
    _set_trial_until(acct_id, future)

    resp = client.get("/", follow_redirects=True)
    assert resp.status_code == 200
    html = resp.text

    assert "Plan: Pro" in html, f"Textul 'Plan: Pro' lipseste in trial. HTML: {html[:800]}"
    assert "trial" in html.lower(), f"Cuvantul 'trial' lipseste in starea de trial. HTML: {html[:800]}"
    assert "18" in html, f"Numarul de zile (18) nu apare in afisaj. HTML: {html[:800]}"
    assert "zile" in html, f"Cuvantul 'zile' lipseste (pluralizare). HTML: {html[:800]}"


def test_afisaj_consum_lunar(client):
    """US-006 + T-6 (5.16): cont free (fara trial) -> linia de plan din burger (pagina
    completa) arata 'Gratuit · N/60 luna asta'. Consumul normal nu mai e rand in corp."""
    acct_id, _ = _create_account_user("consumlun@test.com")
    _login(client, "consumlun@test.com", "parolasecreta10")

    # Dezactiveaza trial-ul (cont free pur)
    _set_trial_until(acct_id, None)
    # Insereaza 5 submissions sent luna asta
    _insert_submissions_sent(acct_id, 5)

    resp = client.get("/", follow_redirects=True)
    assert resp.status_code == 200
    html = resp.text

    assert "Gratuit" in html, f"'Gratuit' lipseste din afisajul de consum. HTML: {html[:800]}"
    assert "5" in html, f"Contorul de consum (5) nu apare. HTML: {html[:800]}"
    assert "60" in html, f"Limita (60) nu apare in afisajul de consum. HTML: {html[:800]}"
    assert "luna asta" in html, f"'luna asta' lipseste din afisajul de consum. HTML: {html[:800]}"


def test_avertizare_aproape_de_limita(client):
    """US-006: >=80% din 60 -> avertizare cu text 'aproape de limita' + culoare warn."""
    acct_id, _ = _create_account_user("aproapelim@test.com")
    _login(client, "aproapelim@test.com", "parolasecreta10")

    _set_trial_until(acct_id, None)
    # 50/60 = 83% -> warn
    _insert_submissions_sent(acct_id, 50)

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

    assert "aproape de limita" in html, (
        f"Textul 'aproape de limita' lipseste la 50/60. HTML: {html[:800]}"
    )
    assert "50" in html, f"Contorul 50 nu apare. HTML: {html[:800]}"
    # Warn = culoare (var(--warn) in inline style)
    assert "var(--warn)" in html or "plan-warn" in html, (
        f"Stilul de warn (var(--warn) sau clasa plan-warn) lipseste la aproape-de-limita. HTML: {html[:800]}"
    )


def test_limita_atinsa(client):
    """US-006: 60/60 -> text 'limita atinsa'."""
    acct_id, _ = _create_account_user("limitaatinsa@test.com")
    _login(client, "limitaatinsa@test.com", "parolasecreta10")

    _set_trial_until(acct_id, None)
    _insert_submissions_sent(acct_id, 60)

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

    assert "limita atinsa" in html, (
        f"Textul 'limita atinsa' lipseste la 60/60. HTML: {html[:800]}"
    )


def test_copy_pluralizare_zi_zile(client):
    """US-006: pluralizare RO corecta — 1 zi (nu '1 zile'), 18 zile (nu '18 zi')."""
    acct_id, _ = _create_account_user("pluralzile@test.com")
    _login(client, "pluralzile@test.com", "parolasecreta10")

    # 18 zile: trebuie "18 zile ramase" (buffer 12h pt delta.days determinist)
    future_18 = (datetime.now(timezone.utc) + timedelta(days=18, hours=12)).strftime("%Y-%m-%d %H:%M:%S")
    _set_trial_until(acct_id, future_18)

    # T-6 (5.16): linia de plan (cu pluralizarea zilelor) traieste in burger pe pagina completa.
    resp = client.get("/", follow_redirects=True)
    assert resp.status_code == 200
    html = resp.text
    assert "18 zile" in html, f"'18 zile' lipseste. HTML: {html[:800]}"
    assert "18 zi " not in html and "18 zi<" not in html, (
        f"'18 zi' (plural gresit) apare in loc de '18 zile'. HTML: {html[:800]}"
    )

    # 1 zi: trebuie "1 zi ramasa" (singular); buffer 12h
    future_1 = (datetime.now(timezone.utc) + timedelta(days=1, hours=12)).strftime("%Y-%m-%d %H:%M:%S")
    _set_trial_until(acct_id, future_1)

    resp = client.get("/", follow_redirects=True)
    assert resp.status_code == 200
    html = resp.text
    assert "1 zi" in html, f"'1 zi' (singular) lipseste la o zi ramasa. HTML: {html[:800]}"
    assert "1 zile" not in html, (
        f"'1 zile' (plural gresit) apare in loc de '1 zi'. HTML: {html[:800]}"
    )


def test_banner_one_time_trial_expirat(client):
    """US-006 T-DES-1: dupa expirarea trial-ului, banner 'Trial Pro expirat' apare in _status.html."""
    acct_id, _ = _create_account_user("trialexp@test.com")
    _login(client, "trialexp@test.com", "parolasecreta10")

    # trial_until in trecut -> trial expirat -> banner one-time
    past = (datetime.now(timezone.utc) - timedelta(days=2)).strftime("%Y-%m-%d %H:%M:%S")
    _set_trial_until(acct_id, past)

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

    assert "Trial Pro expirat" in html, (
        f"Banner 'Trial Pro expirat' lipseste dupa expirarea trial-ului. HTML: {html[:800]}"
    )
    assert "Gratuit" in html, (
        f"Dupa expirarea trial-ului, planul trebuie sa afiseze 'Gratuit'. HTML: {html[:800]}"
    )
    # Bannerul are buton de dismiss
    assert "banner-trial-expirat" in html, (
        f"Elementul id=banner-trial-expirat lipseste. HTML: {html[:800]}"
    )


def test_cont_arata_plan(client):
    """US-006: tab-ul Cont (/tab=cont) afiseaza planul curent si explicatia de upgrade."""
    acct_id, _ = _create_account_user("contplan@test.com")
    _login(client, "contplan@test.com", "parolasecreta10")

    _set_trial_until(acct_id, None)  # free fara trial

    resp = client.get("/?tab=cont", follow_redirects=True)
    assert resp.status_code == 200
    html = resp.text

    assert "Plan curent" in html or "sectiune-plan" in html, (
        f"Sectiunea 'Plan curent' lipseste din tab-ul Cont. HTML: {html[:1000]}"
    )
    assert "Gratuit" in html, f"'Gratuit' lipseste din planul afisat in Cont. HTML: {html[:1000]}"
    assert "Standard" in html or "Pro" in html, (
        f"Optiunile de upgrade (Standard/Pro) lipsesc din sectiunea Plan. HTML: {html[:1000]}"
    )


def test_plan_linie_in_burger(client):
    """US-006: meniul burger contine linia de plan (Plan: Gratuit / Pro · trial N zile)."""
    acct_id, _ = _create_account_user("burgerplan@test.com")
    _login(client, "burgerplan@test.com", "parolasecreta10")

    _set_trial_until(acct_id, None)  # free fara trial

    resp = client.get("/", follow_redirects=True)
    assert resp.status_code == 200
    html = resp.text

    # Meniul burger trebuie sa contina linia de plan
    assert "Plan: Gratuit" in html, (
        f"'Plan: Gratuit' lipseste din meniu burger. HTML (fragment): {html[html.find('cont-menu'):html.find('cont-menu')+500] if 'cont-menu' in html else html[:500]}"
    )


def test_trial_pro_arata_zile_in_burger(client):
    """US-006: cont in trial -> burger arata 'Plan: Pro · trial N zile ramase'."""
    acct_id, _ = _create_account_user("burgertrial@test.com")
    _login(client, "burgertrial@test.com", "parolasecreta10")

    future = (datetime.now(timezone.utc) + timedelta(days=10)).strftime("%Y-%m-%d %H:%M:%S")
    _set_trial_until(acct_id, future)

    resp = client.get("/", follow_redirects=True)
    assert resp.status_code == 200
    html = resp.text

    assert "Plan: Pro" in html, f"'Plan: Pro' lipseste din burger in trial. HTML: {html[:800]}"
    assert "trial" in html.lower(), f"'trial' lipseste din linia de plan din burger. HTML: {html[:800]}"
