"""
P-05b: POST /api/auth/reset-password muss Passwoerter unter 8 Zeichen ablehnen.
Prueft Pydantic-Validierung (HTTP 422) BEVOR die DB befragt wird.
"""
from __future__ import annotations

import os
from unittest.mock import MagicMock, patch

import pytest
from fastapi.testclient import TestClient

os.environ.setdefault("SKIP_DB_MIGRATE", "1")

from main import app


@pytest.fixture
def client() -> TestClient:
    return TestClient(app)


def _mock_db_valid_token() -> MagicMock:
    mock_cur = MagicMock()
    mock_cur.fetchone.return_value = {"profile_id": 1}
    mock_conn = MagicMock()
    mock_cm = MagicMock()
    mock_cm.__enter__.return_value = mock_conn
    mock_cm.__exit__.return_value = False
    return mock_cm, mock_cur


# ── Mindestlaenge-Grenzwerte ──────────────────────────────────────────────────


@pytest.mark.parametrize("short_pw", ["", "a", "1234567"])
def test_reset_password_too_short_rejected(client: TestClient, short_pw: str) -> None:
    """Passwort < 8 Zeichen muss mit 422 abgelehnt werden (Pydantic-Validierung)."""
    r = client.post(
        "/api/auth/reset-password",
        json={"token": "sometoken", "new_password": short_pw},
    )
    assert r.status_code == 422, (
        f"Erwartet 422 fuer Passwort {short_pw!r} ({len(short_pw)} Zeichen), "
        f"erhalten {r.status_code}"
    )


def test_reset_password_exactly_8_chars_accepted(client: TestClient) -> None:
    """Passwort mit genau 8 Zeichen muss die Validierung passieren."""
    mock_cm, mock_cur = _mock_db_valid_token()
    with patch("routers.auth.get_db", return_value=mock_cm), patch(
        "routers.auth.get_cursor", return_value=mock_cur
    ):
        r = client.post(
            "/api/auth/reset-password",
            json={"token": "sometoken", "new_password": "12345678"},
        )
    assert r.status_code == 200
    assert r.json().get("ok") is True


def test_reset_password_long_password_accepted(client: TestClient) -> None:
    """Langes Passwort (>= 8 Zeichen) muss akzeptiert werden."""
    mock_cm, mock_cur = _mock_db_valid_token()
    with patch("routers.auth.get_db", return_value=mock_cm), patch(
        "routers.auth.get_cursor", return_value=mock_cur
    ):
        r = client.post(
            "/api/auth/reset-password",
            json={"token": "sometoken", "new_password": "sicheresPasswort123!"},
        )
    assert r.status_code == 200


def test_reset_password_missing_field_rejected(client: TestClient) -> None:
    """Fehlendes new_password-Feld muss mit 422 abgelehnt werden."""
    r = client.post(
        "/api/auth/reset-password",
        json={"token": "sometoken"},
    )
    assert r.status_code == 422


def test_reset_password_invalid_token_returns_400(client: TestClient) -> None:
    """Gueltiges Passwort aber ungueltiger Token muss 400 liefern."""
    mock_cur = MagicMock()
    mock_cur.fetchone.return_value = None
    mock_conn = MagicMock()
    mock_cm = MagicMock()
    mock_cm.__enter__.return_value = mock_conn
    mock_cm.__exit__.return_value = False
    with patch("routers.auth.get_db", return_value=mock_cm), patch(
        "routers.auth.get_cursor", return_value=mock_cur
    ):
        r = client.post(
            "/api/auth/reset-password",
            json={"token": "ungueltig", "new_password": "validesPw123"},
        )
    assert r.status_code == 400
