"""Teste US-001: endpoint-uri de integrare (GET /v1/ping + export Postman).

TDD — toate testele RED inainte de implementare.
"""

from __future__ import annotations

import json
import os
import tempfile

import pytest
from fastapi.testclient import TestClient


# --------------------------------------------------------------------------- #
# Fixture client izolat                                                        #
# --------------------------------------------------------------------------- #

@pytest.fixture()
def client(monkeypatch):
    """Client FastAPI cu DB temporara izolata, require_api_key=False (dev)."""
    tmp = tempfile.mkdtemp()
    monkeypatch.setenv("AUTOPASS_DB_PATH", os.path.join(tmp, "t.db"))
    monkeypatch.setenv("AUTOPASS_REQUIRE_API_KEY", "false")
    monkeypatch.setenv("AUTOPASS_RAR_ENV", "test")
    from app.config import get_settings
    get_settings.cache_clear()
    from app.main import app
    with TestClient(app) as c:
        yield c
    get_settings.cache_clear()


@pytest.fixture()
def client_prod(monkeypatch):
    """Client cu require_api_key=True (mod prod)."""
    tmp = tempfile.mkdtemp()
    monkeypatch.setenv("AUTOPASS_DB_PATH", os.path.join(tmp, "t.db"))
    monkeypatch.setenv("AUTOPASS_REQUIRE_API_KEY", "true")
    monkeypatch.setenv("AUTOPASS_RAR_ENV", "prod")
    # rar_env=prod declanseaza invarianta de startup (validate_prod_invariants,
    # hardening 2026-07-03): cere si session_secret setat, altfel boot-ul refuza.
    monkeypatch.setenv("AUTOPASS_SESSION_SECRET", "x" * 32)
    from app.config import get_settings
    get_settings.cache_clear()
    from app.main import app
    with TestClient(app) as c:
        yield c
    get_settings.cache_clear()


def _creeaza_cheie(monkeypatch) -> str:
    """Seed cont id=1 + creeaza cheie API; intoarce cheia in clar."""
    from app.db import get_connection
    from app.auth import create_api_key
    conn = get_connection()
    try:
        cheie = create_api_key(conn, 1)
        conn.commit()
    finally:
        conn.close()
    return cheie


def _seteaza_rar_creds(monkeypatch=None) -> None:
    """Seteaza creds RAR pe contul id=1 (slotul per-env, US-013)."""
    from app.db import get_connection
    from app.crypto import encrypt_creds
    conn = get_connection()
    try:
        enc = encrypt_creds({"email": "test@rar.ro", "password": "secret"})
        # US-013: scrie in slotul per-env (test = ancora globala in teste)
        conn.execute(
            "UPDATE accounts SET rar_creds_test_enc=?, rar_test_enabled=1 WHERE id=1", (enc,)
        )
        conn.commit()
    finally:
        conn.close()


# --------------------------------------------------------------------------- #
# Teste ping                                                                   #
# --------------------------------------------------------------------------- #

def test_ping_cu_cheie_valida_200(client, monkeypatch):
    """GET /v1/ping cu X-API-Key valida -> 200 cu campurile cerute."""
    cheie = _creeaza_cheie(monkeypatch)
    r = client.get("/v1/ping", headers={"X-API-Key": cheie})
    assert r.status_code == 200, r.text
    body = r.json()
    assert "account_id" in body
    assert "mediu" in body
    assert "autentificat_cu_cheie" in body
    assert "are_creds_rar" in body
    assert "ts" in body
    assert body["autentificat_cu_cheie"] is True
    assert body["mediu"] == "test"


def test_ping_cu_bearer_valid_200(client, monkeypatch):
    """GET /v1/ping cu Authorization: Bearer valida -> 200, autentificat_cu_cheie=True."""
    cheie = _creeaza_cheie(monkeypatch)
    r = client.get("/v1/ping", headers={"Authorization": f"Bearer {cheie}"})
    assert r.status_code == 200, r.text
    body = r.json()
    assert body["autentificat_cu_cheie"] is True
    assert body["account_id"] == 1


def test_ping_fara_cheie_dev_cont_implicit(client, monkeypatch):
    """Fara cheie, require_api_key=False -> cont 1, autentificat_cu_cheie=False."""
    r = client.get("/v1/ping")
    assert r.status_code == 200, r.text
    body = r.json()
    assert body["account_id"] == 1
    assert body["autentificat_cu_cheie"] is False


def test_ping_x_api_key_gol_in_dev_cont_implicit(client, monkeypatch):
    """X-API-Key cu doar spatii = lipsa cheie -> cont 1, autentificat_cu_cheie=False in dev."""
    r = client.get("/v1/ping", headers={"X-API-Key": "   "})
    assert r.status_code == 200, r.text
    body = r.json()
    assert body["account_id"] == 1
    assert body["autentificat_cu_cheie"] is False


def test_ping_are_creds_rar_reflecta_contul(client, monkeypatch):
    """Cont fara creds -> are_creds_rar=False; dupa setare -> True."""
    # Fara creds
    r1 = client.get("/v1/ping")
    assert r1.status_code == 200
    assert r1.json()["are_creds_rar"] is False

    # Seteaza creds pe cont 1
    _seteaza_rar_creds()

    r2 = client.get("/v1/ping")
    assert r2.status_code == 200
    assert r2.json()["are_creds_rar"] is True


def test_ping_cheie_invalida_401(client, monkeypatch):
    """Cheie invalida -> 401, indiferent de require_api_key."""
    r = client.get("/v1/ping", headers={"X-API-Key": "rfak_cheie_falsa_xxxxxxxx"})
    assert r.status_code == 401


def test_ping_prod_fara_cheie_401(client_prod, monkeypatch):
    """require_api_key=True, fara cheie -> 401."""
    r = client_prod.get("/v1/ping")
    assert r.status_code == 401


def test_ruta_ping_inregistrata_o_singura_data(client, monkeypatch):
    """Ruta /v1/ping trebuie sa apara exact o data in app.routes."""
    from app.main import app
    rute_ping = [r for r in app.routes if hasattr(r, "path") and r.path == "/v1/ping"]
    assert len(rute_ping) == 1, f"Asteptat 1 ruta /v1/ping, gasit: {len(rute_ping)}"


# --------------------------------------------------------------------------- #
# Teste export Postman                                                         #
# --------------------------------------------------------------------------- #

def test_postman_export_json_valid(client, monkeypatch):
    """GET /v1/integrare/postman.json -> 200, Content-Type JSON, structura Postman v2.1.0."""
    r = client.get("/v1/integrare/postman.json")
    assert r.status_code == 200, r.text
    assert "application/json" in r.headers.get("content-type", "")
    body = r.json()
    assert "info" in body
    assert "v2.1.0" in body["info"].get("schema", ""), f"Schema gresita: {body['info'].get('schema')}"


def test_postman_contine_exact_trei_requesturi(client, monkeypatch):
    """Colectia Postman trebuie sa contina exact 3 requesturi cu headers si url corecte."""
    r = client.get("/v1/integrare/postman.json")
    assert r.status_code == 200
    body = r.json()
    items = body.get("item", [])
    assert len(items) == 3, f"Asteptat 3 requesturi, gasit: {len(items)}"

    for item in items:
        req = item.get("request", {})
        # Fiecare trebuie sa aiba header X-API-Key cu valoarea {{api_key}}
        headers = req.get("header", [])
        cheie_header = [h for h in headers if h.get("key") == "X-API-Key"]
        assert len(cheie_header) == 1, f"Header X-API-Key lipsa in request '{item.get('name')}'"
        assert cheie_header[0].get("value") == "{{api_key}}", \
            f"Valoare header gresita: {cheie_header[0].get('value')}"

        # URL-ul trebuie sa contina {{base_url}}
        url = req.get("url", {})
        url_raw = url.get("raw", "") if isinstance(url, dict) else str(url)
        assert "{{base_url}}" in url_raw, \
            f"{{{{base_url}}}} lipsa in url pentru '{item.get('name')}': {url_raw}"


def test_postman_nu_deriva_din_app_routes(client, monkeypatch):
    """Colectia Postman contine EXACT cele 3 rute allowlist, nu mai mult."""
    r = client.get("/v1/integrare/postman.json")
    assert r.status_code == 200
    body = r.json()
    items = body.get("item", [])

    # Extrage URL-urile / path-urile din colectie
    cai_expuse = set()
    for item in items:
        req = item.get("request", {})
        url = req.get("url", {})
        url_raw = url.get("raw", "") if isinstance(url, dict) else str(url)
        # Normalizeaza: scoate {{base_url}} si parametrii query
        cale = url_raw.replace("{{base_url}}", "").split("?")[0]
        cai_expuse.add(cale)

    # Allowlist: exact acestea 3
    allowlist = {"/v1/prezentari", "/v1/import", "/v1/ping"}
    assert cai_expuse == allowlist, \
        f"Colectia expune cai neasteptate: {cai_expuse - allowlist} sau lipsesc: {allowlist - cai_expuse}"
