"""Teste US-013 (PRD 5.10): Tema de culori ROMFAST (accent azur) + tipografie IBM Plex.

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

Testeaza:
- test_paleta_accent_azur_definita: accentul azur ROMFAST definit corect in :root si [data-theme="light"]
- test_font_ibm_plex_aplicat: IBM Plex Sans + Mono declarate in font-family si @font-face
- test_contrast_aa_pe_text_principal: contrast text principal >= 4.5:1 in dark si light
"""

from __future__ import annotations

import os
import re
import tempfile

import pytest
from starlette.testclient import TestClient


@pytest.fixture()
def client(monkeypatch):
    tmp = tempfile.mkdtemp()
    monkeypatch.setenv("AUTOPASS_DB_PATH", os.path.join(tmp, "culori.db"))
    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 _get_style_block(html: str) -> str:
    """Extrage continutul primului <style> din HTML."""
    m = re.search(r"<style>(.*?)</style>", html, re.DOTALL)
    assert m, "<style> negasit in HTML"
    return m.group(1)


def _hex_to_srgb(hex_color: str) -> tuple[float, float, float]:
    """Converteste hex (#rrggbb) la tuple (r, g, b) in [0,1]."""
    h = hex_color.lstrip("#")
    assert len(h) == 6, f"Hex invalid: {hex_color}"
    r = int(h[0:2], 16) / 255.0
    g = int(h[2:4], 16) / 255.0
    b = int(h[4:6], 16) / 255.0
    return r, g, b


def _linearize(c: float) -> float:
    """Liniarizeaza o componenta sRGB pentru calcul luminanta WCAG."""
    if c <= 0.04045:
        return c / 12.92
    return ((c + 0.055) / 1.055) ** 2.4


def _luminance(hex_color: str) -> float:
    """Calculeaza luminanta relativa WCAG 2.1 pentru o culoare hex."""
    r, g, b = _hex_to_srgb(hex_color)
    rl = _linearize(r)
    gl = _linearize(g)
    bl = _linearize(b)
    return 0.2126 * rl + 0.7152 * gl + 0.0722 * bl


def _contrast_ratio(c1: str, c2: str) -> float:
    """Calculeaza raportul de contrast WCAG 2.1 intre doua culori hex."""
    l1 = _luminance(c1)
    l2 = _luminance(c2)
    lighter = max(l1, l2)
    darker = min(l1, l2)
    return (lighter + 0.05) / (darker + 0.05)


# ── test_paleta_accent_azur_definita ─────────────────────────────────────────

def test_paleta_accent_azur_definita(client):
    """Accentul azur ROMFAST definit corect si neutrele actualizate conform DESIGN.md.

    :root (dark default):
      --accent:#2E74D6
      --bg:#0f1218  --card:#181c24  --ink:#e6e9ef  --muted:#8b93a7  --line:#262b36
      --ok:#2FBF8F  --warn:#E0A93B  --err:#E05D5D

    [data-theme="light"]:
      --accent:#1F66C9
      --bg:#f5f7fa  --card:#ffffff  --ink:#1a1d24  --muted:#5c6473  --line:#e2e5ea
      --ok:#15803d  --warn:#b45309  --err:#dc2626
    """
    resp = client.get("/login")
    assert resp.status_code == 200
    style = _get_style_block(resp.text)

    # Paleta dark (:root)
    dark_vars = {
        "--accent": "#2E74D6",
        "--bg": "#0f1218",
        "--card": "#181c24",
        "--ink": "#e6e9ef",
        "--muted": "#8b93a7",
        "--line": "#262b36",
        "--ok": "#2FBF8F",
        "--warn": "#E0A93B",
        "--err": "#E05D5D",
    }
    # Extrage blocul :root
    root_m = re.search(r":root\s*\{([^}]+)\}", style, re.DOTALL)
    assert root_m, "Blocul :root negasit in <style>"
    root_block = root_m.group(1)

    for var, val in dark_vars.items():
        assert val.lower() in root_block.lower(), (
            f"Variabila {var}:{val} lipseste sau are valoare gresita in :root (dark). "
            f"Continut :root: {root_block.strip()}"
        )

    # Paleta light ([data-theme="light"])
    light_vars = {
        "--accent": "#1F66C9",
        "--bg": "#f5f7fa",
        "--card": "#ffffff",
        "--ink": "#1a1d24",
        "--muted": "#5c6473",
        "--line": "#e2e5ea",
        "--ok": "#15803d",
        "--warn": "#b45309",
        "--err": "#dc2626",
    }
    light_m = re.search(r'\[data-theme=["\']light["\']\]\s*\{([^}]+)\}', style, re.DOTALL)
    assert light_m, 'Blocul [data-theme="light"] negasit in <style>'
    light_block = light_m.group(1)

    for var, val in light_vars.items():
        assert val.lower() in light_block.lower(), (
            f"Variabila {var}:{val} lipseste sau are valoare gresita in [data-theme=\"light\"]. "
            f"Continut light: {light_block.strip()}"
        )


# ── test_font_system_stack_aplicat ───────────────────────────────────────────

def test_font_system_stack_aplicat(client):
    """US-001 (PRD 5.16): IBM Plex eliminat; body foloseste stiva de fonturi sistem.

    Verifica:
    - body font-family foloseste var(--font-ui) (CSS custom property)
    - --font-ui este definit in :root si contine un system font stack (system-ui / -apple-system)
    - ZERO @font-face cu 'IBM Plex' in <style> (IBM Plex eliminat complet)
    - ZERO referinte catre /static/fonts/ in HTML (nu se mai servesc fisiere woff2)
    """
    resp = client.get("/login")
    assert resp.status_code == 200
    style = _get_style_block(resp.text)

    # 1. body font-family refera var(--font-ui) (nu IBM Plex inline)
    body_m = re.search(r"body\s*\{([^}]+)\}", style, re.DOTALL)
    assert body_m, "Regula 'body { ... }' negasita in <style>"
    body_block = body_m.group(1)
    assert "var(--font-ui)" in body_block, (
        f"body font-family trebuie sa foloseasca var(--font-ui) (sistem font stack). "
        f"body block: {body_block.strip()}"
    )

    # 2. --font-ui definit in :root si contine un system font stack
    root_m = re.search(r":root\s*\{([^}]+)\}", style, re.DOTALL)
    assert root_m, "Blocul :root negasit in <style>"
    root_block = root_m.group(1)
    assert "--font-ui" in root_block, (
        f"--font-ui lipseste din :root. Continut :root: {root_block.strip()}"
    )
    font_ui_m = re.search(r"--font-ui\s*:\s*([^;]+)", root_block)
    assert font_ui_m, "--font-ui negasit in blocul :root"
    font_ui_val = font_ui_m.group(1).lower()
    assert "system-ui" in font_ui_val or "-apple-system" in font_ui_val, (
        f"--font-ui trebuie sa contina system-ui sau -apple-system (stiva sistem). "
        f"Valoare gasita: {font_ui_m.group(1).strip()}"
    )

    # 3. ZERO @font-face cu IBM Plex (eliminat in US-001)
    font_face_blocks = re.findall(r"@font-face\s*\{([^}]+)\}", style, re.DOTALL)
    ibm_face = [b for b in font_face_blocks if "IBM Plex" in b or "ibm-plex" in b.lower()]
    assert not ibm_face, (
        f"@font-face cu IBM Plex trebuia eliminat (US-001 PRD 5.16). "
        f"Blocat gasit: {ibm_face}"
    )

    # 4. ZERO referinte /static/fonts/ in HTML randat (nu mai servim woff2)
    html = resp.text
    assert "/static/fonts/" not in html, (
        "Referinte catre /static/fonts/ gasite in HTML — trebuie eliminate (US-001 PRD 5.16)."
    )


# ── test_contrast_aa_pe_text_principal ───────────────────────────────────────

def test_contrast_aa_pe_text_principal(client):
    """Contrastul text principal este >= 4.5:1 in dark si light (WCAG 2.1 AA).

    Dark: --ink:#e6e9ef pe --bg:#0f1218
    Light: --ink:#1a1d24 pe --bg:#f5f7fa
    Accent ca text pe alb: #1F66C9 pe #ffffff (WCAG AA pentru text normal)
    """
    resp = client.get("/login")
    assert resp.status_code == 200
    style = _get_style_block(resp.text)

    # Extrage valorile de culoare din :root si [data-theme="light"]
    def _extract_var(block: str, var_name: str) -> str | None:
        m = re.search(
            re.escape(var_name) + r"\s*:\s*(#[0-9a-fA-F]{6})",
            block,
            re.IGNORECASE,
        )
        return m.group(1) if m else None

    root_m = re.search(r":root\s*\{([^}]+)\}", style, re.DOTALL)
    assert root_m, "Blocul :root negasit"
    root_block = root_m.group(1)

    light_m = re.search(r'\[data-theme=["\']light["\']\]\s*\{([^}]+)\}', style, re.DOTALL)
    assert light_m, 'Blocul [data-theme="light"] negasit'
    light_block = light_m.group(1)

    # --- Dark: ink pe bg ---
    dark_ink = _extract_var(root_block, "--ink")
    dark_bg = _extract_var(root_block, "--bg")
    assert dark_ink and dark_bg, (
        f"Nu am putut extrage --ink/{dark_ink} sau --bg/{dark_bg} din :root"
    )
    cr_dark = _contrast_ratio(dark_ink, dark_bg)
    assert cr_dark >= 4.5, (
        f"Contrast dark insuficient: {dark_ink} pe {dark_bg} = {cr_dark:.2f}:1 (minim 4.5:1 AA)"
    )

    # --- Light: ink pe bg ---
    light_ink = _extract_var(light_block, "--ink")
    light_bg = _extract_var(light_block, "--bg")
    assert light_ink and light_bg, (
        f"Nu am putut extrage --ink/{light_ink} sau --bg/{light_bg} din [data-theme=light]"
    )
    cr_light = _contrast_ratio(light_ink, light_bg)
    assert cr_light >= 4.5, (
        f"Contrast light insuficient: {light_ink} pe {light_bg} = {cr_light:.2f}:1 (minim 4.5:1 AA)"
    )

    # --- Accent ca text pe alb (tema light) ---
    light_accent = _extract_var(light_block, "--accent")
    assert light_accent, f"--accent negasit in [data-theme=light]: {light_block.strip()}"
    cr_accent_white = _contrast_ratio(light_accent, "#ffffff")
    assert cr_accent_white >= 4.5, (
        f"Accent light ({light_accent}) pe alb: contrast {cr_accent_white:.2f}:1 < 4.5:1 AA. "
        f"Foloseste o varianta mai inchisa (ex. #1F66C9)."
    )
