"""Teste US-004 (PRD 5.11): Rand filtre Trimiteri — layout + stil ca referinta.

TDD — testele sunt scrise INAINTE de implementare (RED), apoi devin GREEN.

Verifica:
  - Quick-pills de data (Azi/7 zile/30 zile) in STANGA, inainte de campul vehicul si de pills-stare
  - Pill-urile folosesc stil uniform (color-mix la hover, nu filter:brightness)
  - Quick-pills seteaza data_de/data_pana si reincarca lista pastrand starea activa
"""

from __future__ import annotations

import json
import os
import re
import tempfile

import pytest
from starlette.testclient import TestClient


# ============================================================
# Helpers
# ============================================================

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, f"Service {email}", active=True)
        create_user(conn, acct_id, email, password)
        return acct_id
    finally:
        conn.close()


def _login(client, email: str, password: str = "parolasecreta10") -> None:
    resp = client.get("/login")
    m = re.search(r'name="csrf_token"\s+value="([^"]+)"', resp.text) or \
        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}"


def _ins(acct: int, *, status: str = "needs_mapping") -> int:
    from app.db import get_connection

    conn = get_connection()
    try:
        cur = conn.execute(
            "INSERT INTO submissions (idempotency_key, account_id, status, payload_json) VALUES (?, ?, ?, ?)",
            (
                f"k-us004-{os.urandom(4).hex()}",
                acct,
                status,
                json.dumps({
                    "vin": "WVWZZZ1KZAW009999",
                    "nr_inmatriculare": "B001TST",
                    "data_prestatie": "2026-06-20",
                    "odometru_final": "100000",
                    "prestatii": [{"cod_prestatie": "OE-1"}],
                }),
            ),
        )
        conn.commit()
        return int(cur.lastrowid)
    finally:
        conn.close()


# ============================================================
# Fixture
# ============================================================

@pytest.fixture()
def client(monkeypatch):
    tmp = tempfile.mkdtemp()
    monkeypatch.setenv("AUTOPASS_DB_PATH", os.path.join(tmp, "filtre_us004.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()


# ============================================================
# test_pill_uri_in_stanga_controalelor
# ============================================================

def test_pill_uri_in_stanga_controalelor(client):
    """Quick-pills de data (Azi/7 zile/30 zile) apar in STANGA formularului de filtre.

    Ordinea in DOM: quick-pills → camp cautare vehicul → pills stare.
    Pill-urile de stare NU mai stau izolate la dreapta butonului Filtreaza cu margin-left:auto
    pe un span separat — layout-ul e controlat explicit prin pozitia in form.
    """
    acct = _create_account_user("stanga@test.com")
    _ins(acct, status="needs_mapping")
    _login(client, "stanga@test.com")

    resp = client.get("/?tab=acasa")
    assert resp.status_code == 200
    html = resp.text

    # Quick-pills trebuie sa fie prezente in forma
    assert "Azi" in html, "Quick-pill 'Azi' trebuie sa fie prezent in bara de filtre"
    assert "7 zile" in html, "Quick-pill '7 zile' trebuie sa fie prezent in bara de filtre"
    assert "30 zile" in html, "Quick-pill '30 zile' trebuie sa fie prezent in bara de filtre"

    # DOM order: quick-pills STANGA (index mai mic in HTML) fata de campul vehicul
    idx_azi = html.find("Azi")
    idx_vehicul = html.find('id="f-vehicul"')
    assert idx_azi != -1, "'Azi' nu s-a gasit in HTML"
    assert idx_vehicul != -1, "'f-vehicul' nu s-a gasit in HTML"
    assert idx_azi < idx_vehicul, (
        "Quick-pill 'Azi' trebuie sa apara INAINTE de campul f-vehicul in DOM (stanga)"
    )

    # Pills stare (pills-categorii) la DREAPTA (dupa vehicul)
    idx_pills_cat = html.find('id="pills-categorii"')
    assert idx_pills_cat != -1, "pills-categorii nu s-a gasit in HTML"
    assert idx_vehicul < idx_pills_cat, (
        "Campul vehicul trebuie sa apara INAINTE de pills-categorii in DOM (pills-stare la dreapta)"
    )

    # Quick-pills apar si inainte de pills-categorii (stanga totala)
    assert idx_azi < idx_pills_cat, (
        "Quick-pills de data trebuie sa apara INAINTE de pills-categorii"
    )


# ============================================================
# test_pill_categorie_stil_uniform
# ============================================================

def test_pill_categorie_stil_uniform(client):
    """Pill-urile au un singur stil uniform: hover cu color-mix, activ suprima hover.

    - Hover trebuie sa foloseasca color-mix(in srgb, currentColor 12%, transparent)
      si NU filter:brightness (care devenea rosu plin si ilizibil).
    - Focus :focus-visible pastrat pe pill-cat.
    - Pill-cat-reset activ = --accent; pill-cat activ = culoarea categoriei (nu toate accent).
    """
    acct = _create_account_user("stil@test.com")
    _login(client, "stil@test.com")

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

    # CSS-ul trebuie sa contina color-mix pentru hover pe pill-cat
    assert "color-mix" in html, (
        "pill-cat:hover trebuie sa foloseasca color-mix, nu filter:brightness"
    )

    # CSS-ul NU trebuie sa foloseasca filter:brightness pe .pill-cat:hover
    m = re.search(r'\.pill-cat:hover\s*\{([^}]*)\}', html)
    if m:
        hover_rule = m.group(1)
        assert "brightness" not in hover_rule, (
            f"pill-cat:hover NU trebuie sa contina filter:brightness — regula gasita: {hover_rule}"
        )

    # focus-visible pastrat pe pill-cat
    assert "pill-cat:focus-visible" in html, (
        "pill-cat trebuie sa pastreze regula :focus-visible cu outline"
    )

    # Pill-cat-reset activ foloseste --accent (nu culoarea categoriei)
    assert "pill-cat-reset" in html, "Clasa pill-cat-reset trebuie sa existe pentru butonul Toate"
    assert "var(--accent)" in html, (
        "Pill Toate activ trebuie sa foloseasca var(--accent)"
    )


# ============================================================
# test_quick_pills_data_seteaza_interval
# ============================================================

def test_quick_pills_data_seteaza_interval(client):
    """Quick-pills de data seteaza data_de/data_pana (preset) si reincarca lista HTMX.

    Pastrand pill-ul de stare activ: setDataRange NU schimba campul #f-status.
    """
    acct = _create_account_user("datepill@test.com")
    _ins(acct, status="needs_mapping")
    _login(client, "datepill@test.com")

    resp = client.get("/?tab=acasa")
    assert resp.status_code == 200
    html = resp.text

    # Trebuie sa existe un mecanism JS care seteaza data_de si data_pana
    assert "setDataRange" in html, (
        "Quick-pills trebuie sa apeleze setDataRange (functie JS pentru setarea intervalului de date)"
    )

    # setDataRange trebuie sa seteze campul data_de/data_pana (prin id sau name)
    assert "f-data-de" in html or "data_de" in html, (
        "setDataRange trebuie sa seteze campul data_de (prin id f-data-de sau name data_de)"
    )
    assert "f-data-pana" in html or "data_pana" in html, (
        "setDataRange trebuie sa seteze campul data_pana (prin id f-data-pana sau name data_pana)"
    )

    # Lista trebuie sa se reincarce prin form (HTMX) la click pe quick-pill
    assert "/_fragments/submissions" in html, (
        "Formularul de filtre trebuie sa trimita catre /_fragments/submissions"
    )

    # setDataRange NU trebuie sa schimbe campul de status (pastreaza pill-ul de stare activ)
    # Verificam ca in JS-ul setDataRange nu se face `hs.value = ` (schimbare status)
    # prin cautarea functiei in HTML
    idx_fn = html.find("setDataRange")
    assert idx_fn != -1
    # Extrage corpul functiei (pana la urmatoarea definitie de functie mare)
    fn_body = html[idx_fn:idx_fn + 800]
    assert "f-status" not in fn_body or "hs.value" not in fn_body[:fn_body.find("f-data")], (
        "setDataRange NU trebuie sa modifice campul f-status (pastreaza filtrul de stare)"
    )


# ============================================================
# test_custom_pill_prezent_si_dezvaluie_campuri
# ============================================================

def test_custom_pill_prezent_si_dezvaluie_campuri(client):
    """Butonul Custom este al 4-lea quick-pill si dezvaluie campurile de data manuala.

    AC US-004: Azi / 7 zile / 30 zile / Custom (4 quick-pills).
    Custom NU seteaza un preset; dezvaluie #custom-date-fields cu focus pe #f-data-de.
    Campurile #f-data-de/#f-data-pana sunt de tip 'date' (nu hidden) pentru interactiune.
    """
    acct = _create_account_user("custom@test.com")
    _ins(acct, status="needs_mapping")
    _login(client, "custom@test.com")

    resp = client.get("/?tab=acasa")
    assert resp.status_code == 200
    html = resp.text

    # Butonul Custom trebuie sa fie prezent in quick-pills
    assert "Custom" in html, "Butonul 'Custom' trebuie sa fie prezent in bara de filtre (4 quick-pills)"

    # Butonul Custom apeleaza setDataRange cu 'custom'
    assert "setDataRange" in html and "'custom'" in html, (
        "Butonul Custom trebuie sa apeleze setDataRange(this,'custom')"
    )

    # In ramura 'custom' din JS, NU se apeleaza requestSubmit/form.submit
    # (se dezvaluie campurile; utilizatorul introduce datele si form-ul submite la change)
    # Cautam in JS (range === 'custom'), nu in atributul onclick al butonului
    idx_fn = html.find("range === 'custom'")
    assert idx_fn != -1, "Conditia `range === 'custom'` trebuie sa existe in JS (setDataRange)"
    # Cautam in blocul imediat urmator conditiei: trebuie sa apara 'return'
    # INAINTE de 'requestSubmit' (dovada ca nu submite automat in ramura custom)
    block_custom = html[idx_fn:idx_fn + 500]
    idx_return = block_custom.find("return")
    idx_submit = block_custom.find("requestSubmit")
    assert idx_return != -1, (
        "Ramura 'custom' din setDataRange trebuie sa contina 'return' pentru a nu submite automat"
    )
    assert idx_submit == -1 or idx_return < idx_submit, (
        "Ramura 'custom' NU trebuie sa apeleze requestSubmit inainte de 'return'"
    )

    # Campurile de data trebuie sa existe si sa fie de tip 'date' (nu hidden)
    # pentru ca utilizatorul sa le poata interactiona in modul Custom
    import re
    m_de = re.search(r'<input[^>]+id="f-data-de"[^>]*>', html)
    assert m_de, "Input #f-data-de negasit in HTML"
    tag_de = m_de.group(0)
    assert 'type="hidden"' not in tag_de, (
        "Input #f-data-de NU trebuie sa fie type='hidden' — trebuie sa fie tip 'date' "
        "pentru interactiune in modul Custom"
    )
