"""Teste US-007 (PRD 3.3b): sectiunea 'Contul meu' — rotire cheie API + creds RAR din UI.

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

Rute testate:
- GET  /_fragments/cont       -> card "Contul meu"
- POST /cont/roteste-cheie    -> cheie noua afisata o singura data
"""

from __future__ import annotations

import os
import re
import tempfile

import pytest
from starlette.testclient import TestClient


@pytest.fixture()
def client(monkeypatch):
    """Client fara web_auth_required (dev mode) — sesiunea se seteaza manual."""
    tmp = tempfile.mkdtemp()
    monkeypatch.setenv("AUTOPASS_DB_PATH", os.path.join(tmp, "t.db"))
    from app.config import get_settings
    get_settings.cache_clear()
    from app.main import app
    with TestClient(app, follow_redirects=False) as c:
        yield c
    get_settings.cache_clear()


@pytest.fixture()
def client_prod(monkeypatch):
    """Client cu web_auth_required=True (mod prod) — CSRF enforce."""
    tmp = tempfile.mkdtemp()
    monkeypatch.setenv("AUTOPASS_DB_PATH", os.path.join(tmp, "t.db"))
    monkeypatch.setenv("AUTOPASS_WEB_AUTH_REQUIRED", "true")
    from app.config import get_settings
    get_settings.cache_clear()
    from app.main import app
    with TestClient(app, follow_redirects=False) as c:
        yield c
    get_settings.cache_clear()


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

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


def _login(client, email: str, password: str) -> None:
    """Face login real prin HTTP si seteaza cookie-ul de sesiune pe client."""
    # Obtine CSRF token de pe pagina de login
    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,
    })
    # 303 redirect la / inseamna login reusit
    assert resp.status_code == 303, f"Login esuat: {resp.status_code} {resp.text[:200]}"


def _get_csrf_from_fragment(client) -> str:
    """Obtine CSRF token din fragmentul /_fragments/cont."""
    resp = client.get("/_fragments/cont")
    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, f"csrf_token negasit in /_fragments/cont: {resp.text[:500]}"
    return m.group(1)


# ============================================================
# test_roteste_cheie_afisata_o_data
# ============================================================

def test_roteste_cheie_afisata_o_data(client):
    """User logat roteste cheia: raspunsul contine 'rfak_'; cheia veche revocata."""
    acct_id, user_id, api_key_initiala = _create_account_user("roteste@test.com")
    _login(client, "roteste@test.com", "parolasecreta10")

    csrf = _get_csrf_from_fragment(client)
    resp = client.post("/cont/roteste-cheie", data={"csrf_token": csrf})

    assert resp.status_code == 200
    assert "rfak_" in resp.text, f"Cheia noua nu apare in raspuns: {resp.text[:500]}"

    # Verifica in DB: cheia veche revocata, una noua activa
    from app.db import get_connection
    conn = get_connection()
    try:
        rows = conn.execute(
            "SELECT id, active FROM api_keys WHERE account_id=? ORDER BY id",
            (acct_id,),
        ).fetchall()
        # Trebuie sa avem minim 2 chei: cea initiala (active=0) si cea noua (active=1)
        active_keys = [r for r in rows if r["active"] == 1]
        inactive_keys = [r for r in rows if r["active"] == 0]
        assert len(active_keys) == 1, f"Trebuia exact 1 cheie activa, gasit: {len(active_keys)}"
        assert len(inactive_keys) >= 1, "Cheia veche trebuia revocata (active=0)"
    finally:
        conn.close()


# ============================================================
# test_roteste_fara_csrf_403_in_prod
# ============================================================

def test_roteste_fara_csrf_403_in_prod(client_prod):
    """Prod + sesiune autentificata + CSRF lipsa -> 403."""
    # Cream cont + user
    acct_id, user_id, _ = _create_account_user("csrf_test@test.com")

    # Login real
    _login(client_prod, "csrf_test@test.com", "parolasecreta10")

    # POST fara csrf_token (sau cu token gresit)
    resp = client_prod.post("/cont/roteste-cheie", data={"csrf_token": "token_gresit"})
    assert resp.status_code == 403, f"Trebuia 403, got {resp.status_code}"


# ============================================================
# test_fragment_cont_nelogat_redirect
# ============================================================

def test_fragment_cont_nelogat_redirect(monkeypatch):
    """Fara sesiune + web_auth_required=True -> 303 redirect /login."""
    tmp = tempfile.mkdtemp()
    monkeypatch.setenv("AUTOPASS_DB_PATH", os.path.join(tmp, "t_nl.db"))
    monkeypatch.setenv("AUTOPASS_WEB_AUTH_REQUIRED", "true")
    from app.config import get_settings
    get_settings.cache_clear()
    from app.main import app
    with TestClient(app, follow_redirects=False) as c:
        resp = c.get("/_fragments/cont")
        assert resp.status_code == 303
        assert "/login" in resp.headers.get("location", "")
    get_settings.cache_clear()


# ============================================================
# US-002: sectiunea 'Date firma' + banner cont incomplet
# ============================================================

def _create_complete_account(
    name: str = "Firma Test SRL",
    login_email: str = "firma_test@test.com",
    account_email: str = "contact@firma.com",
    cui: str = "RO12345678",
    password: str = "parolasecreta10",
):
    """Creeaza cont COMPLET (name+email+CUI) + 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, name, cui=cui, email=account_email, active=True)
        user_id = create_user(conn, acct_id, login_email, password)
        return acct_id, user_id
    finally:
        conn.close()


def test_cont_afiseaza_companie_email_cui(client):
    """Fragment /_fragments/cont contine sectiunea 'Date firma' cu companie, email, CUI prefilled."""
    _create_complete_account(
        name="Test Firma SRL",
        login_email="tfirma@test.com",
        account_email="contact_tf@test.com",
        cui="RO11111111",
    )
    _login(client, "tfirma@test.com", "parolasecreta10")

    resp = client.get("/_fragments/cont")
    assert resp.status_code == 200
    assert "Date firma" in resp.text or "date-firma" in resp.text, \
        f"Sectiunea 'Date firma' lipseste: {resp.text[:500]}"
    assert "Test Firma SRL" in resp.text, f"Compania nu e prefilled: {resp.text[:500]}"
    assert "contact_tf@test.com" in resp.text, f"Email-ul nu e prefilled: {resp.text[:500]}"
    assert "RO11111111" in resp.text, f"CUI-ul nu e prefilled: {resp.text[:500]}"


def test_post_date_firma_actualizeaza(client):
    """POST /cont/date-firma actualizeaza accounts.name, accounts.email, accounts.cui in DB."""
    acct_id, user_id, _ = _create_account_user("update_df@test.com")
    _login(client, "update_df@test.com", "parolasecreta10")

    csrf = _get_csrf_from_fragment(client)

    resp = client.post("/cont/date-firma", data={
        "csrf_token": csrf,
        "companie": "Firma Actualizata SRL",
        "email": "contact@firma-act.com",
        "cui": "RO99887766",
    })
    assert resp.status_code == 200, f"POST /cont/date-firma a returnat {resp.status_code}"

    # Verifica in DB ca datele au fost actualizate
    from app.db import get_connection
    conn = get_connection()
    try:
        row = conn.execute(
            "SELECT name, email, cui FROM accounts WHERE id=?", (acct_id,)
        ).fetchone()
        assert row["name"] == "Firma Actualizata SRL", f"name neschimbat: {row['name']}"
        assert row["email"] == "contact@firma-act.com", f"email neschimbat: {row['email']}"
        assert row["cui"] == "RO99887766", f"cui neschimbat: {row['cui']}"
    finally:
        conn.close()


def test_post_date_firma_cui_duplicat_eroare(client):
    """POST /cont/date-firma cu CUI deja folosit de alt cont -> eroare in raspuns."""
    # Cont A cu CUI existent
    _create_complete_account(
        name="Firma A SRL",
        login_email="firma_a_dup@test.com",
        account_email="a_dup@test.com",
        cui="ROAAA11111",
    )
    # Cont B fara CUI
    acct_b, user_b, _ = _create_account_user("firma_b_dup@test.com")

    _login(client, "firma_b_dup@test.com", "parolasecreta10")
    csrf = _get_csrf_from_fragment(client)

    resp = client.post("/cont/date-firma", data={
        "csrf_token": csrf,
        "companie": "Firma B SRL",
        "email": "firma_b_dup@test.com",
        "cui": "ROAAA11111",  # CUI-ul lui A — duplicat
    })
    assert resp.status_code == 200
    text = resp.text.lower()
    assert "deja" in text or "duplicat" in text or "folosit" in text or "eroare" in text, \
        f"Mesaj eroare CUI duplicat lipsa: {resp.text[:500]}"

    # Contul B nu trebuie sa aiba CUI-ul lui A in DB
    from app.db import get_connection
    conn = get_connection()
    try:
        row = conn.execute("SELECT cui FROM accounts WHERE id=?", (acct_b,)).fetchone()
        assert row["cui"] != "ROAAA11111", "CUI-ul duplicat a fost totusi salvat in DB"
    finally:
        conn.close()


def test_banner_cont_incomplet_pe_legacy(client):
    """Acasa afiseaza banner 'Completeaza datele firmei' cand contul e incomplet (fara email/CUI)."""
    # Cont fara email/CUI (legacy: creat fara aceste campuri)
    _create_account_user("legacy_test@test.com")
    _login(client, "legacy_test@test.com", "parolasecreta10")

    resp = client.get("/")
    assert resp.status_code == 200
    text = resp.text.lower()
    # Banner trebuie sa apara cand contul e incomplet
    assert "completeaza" in text or "date firm" in text or "incomplet" in text, \
        f"Banner 'Completeaza datele firmei' lipsa pe Acasa: {resp.text[:2000]}"
