"""Tests for auth blueprint (client/blueprints/auth.py).

Covers login GET/POST, logout, unauthenticated redirect, and language/theme switch.
"""
import pytest
from unittest.mock import patch


class TestLoginPage:
    """GET /auth/login tests."""

    def test_login_page_renders(self, client):
        """Login page renders successfully with 200 status."""
        resp = client.get("/auth/login")
        assert resp.status_code == 200
        assert b"login" in resp.data.lower() or b"Login" in resp.data

    def test_login_page_redirects_when_already_logged_in(self, logged_in_client):
        """Already authenticated user is redirected away from login."""
        resp = logged_in_client.get("/auth/login")
        assert resp.status_code == 302


class TestLoginPost:
    """POST /auth/login tests."""

    def test_login_post_success_redirects(self, client, mock_api_client):
        """Successful login POST sets session and redirects."""
        mock_api_client.post.return_value = {
            "api_key": "new-api-key-abc",
            "user": {
                "id": 1,
                "username": "testuser",
                "display_name": "Test User",
                "roles": ["MeasurementTec"],
                "is_admin": False,
                "language_pref": "en",
                "theme_pref": "light",
                "active": True,
            },
        }
        # Mock settings call made after login
        mock_api_client.get.return_value = {}

        resp = client.post(
            "/auth/login",
            data={"username": "testuser", "password": "pass123"},
            follow_redirects=False,
        )
        assert resp.status_code == 302
        mock_api_client.post.assert_called_once()

        # Verify session was populated
        with client.session_transaction() as sess:
            assert sess.get("api_key") == "new-api-key-abc"
            assert sess["user"]["username"] == "testuser"

    def test_login_post_error_shows_error(self, client, mock_api_client):
        """Failed login returns the login page with error flash."""
        mock_api_client.post.return_value = {
            "error": True,
            "detail": "Credenziali non valide",
        }

        resp = client.post(
            "/auth/login",
            data={"username": "bad", "password": "wrong"},
            follow_redirects=True,
        )
        assert resp.status_code == 200
        # Error message should appear in the response (flashed)
        assert b"Credenziali non valide" in resp.data or b"login" in resp.data.lower()

    def test_login_post_empty_fields(self, client, mock_api_client):
        """Login with empty username/password shows validation error."""
        resp = client.post(
            "/auth/login",
            data={"username": "", "password": ""},
            follow_redirects=True,
        )
        assert resp.status_code == 200
        # Should render login again (not crash)


class TestLogout:
    """GET/POST /auth/logout tests."""

    def test_logout_clears_session(self, logged_in_client, mock_api_client):
        """Logout clears session and redirects to login."""
        mock_api_client.post.return_value = {}

        resp = logged_in_client.get("/auth/logout", follow_redirects=False)
        assert resp.status_code == 302
        assert "/auth/login" in resp.headers["Location"]

        # Session should be cleared
        with logged_in_client.session_transaction() as sess:
            assert "api_key" not in sess
            assert "user" not in sess


class TestUnauthenticatedRedirect:
    """Protected routes redirect unauthenticated users."""

    def test_profile_requires_login(self, client):
        """Profile page redirects to login when not authenticated."""
        resp = client.get("/auth/profile", follow_redirects=False)
        assert resp.status_code == 302
        assert "/auth/login" in resp.headers["Location"]


class TestLanguageSwitch:
    """Language and theme switching via app routes."""

    def test_set_language_stores_in_session(self, client):
        """Setting language updates session and redirects back."""
        resp = client.get("/set-language/en", follow_redirects=False)
        assert resp.status_code == 302

        with client.session_transaction() as sess:
            assert sess.get("language") == "en"

    def test_set_language_invalid_ignored(self, client):
        """Setting an unsupported language does not crash and still redirects."""
        resp = client.get("/set-language/xx", follow_redirects=False)
        assert resp.status_code == 302

        with client.session_transaction() as sess:
            # Invalid language should NOT be stored
            assert sess.get("language") != "xx"
