"""Tests for internationalization (i18n) functionality"""

import pytest

pytestmark = [pytest.mark.unit, pytest.mark.utils]

from flask import session
from app import create_app, db
from app.models import User
from flask_babel import get_locale


class TestI18nConfiguration:
    """Test internationalization configuration"""

    def test_supported_languages_configured(self, client):
        """Test that all supported languages are configured"""
        with client.application.app_context():
            languages = client.application.config.get("LANGUAGES", {})

            # Check that all required languages are present
            assert "en" in languages
            assert "de" in languages
            assert "fr" in languages
            assert "es" in languages
            assert "ar" in languages
            assert "he" in languages
            assert "nl" in languages
            assert "it" in languages
            assert "fi" in languages
            assert "pt" in languages

            # Check that language labels are set
            assert languages["en"] == "English"
            assert languages["es"] == "Español"
            assert languages["pt"] == "Português"
            assert languages["ar"] == "العربية"
            assert languages["he"] == "עברית"

    def test_rtl_languages_configured(self, client):
        """Test that RTL languages are configured"""
        with client.application.app_context():
            rtl_languages = client.application.config.get("RTL_LANGUAGES", set())

            # Check that RTL languages are present
            assert "ar" in rtl_languages
            assert "he" in rtl_languages

            # Check that LTR languages are not in RTL set
            assert "en" not in rtl_languages
            assert "de" not in rtl_languages
            assert "es" not in rtl_languages

    def test_default_locale_is_english(self, client):
        """Test that default locale is English"""
        with client.application.app_context():
            default_locale = client.application.config.get("BABEL_DEFAULT_LOCALE")
            assert default_locale == "en"


class TestLocaleSelection:
    """Test locale selection logic"""

    def test_locale_from_user_preference(self, client, test_user):
        """Test that locale is selected from user's preference"""
        # Set user's preferred language
        test_user.preferred_language = "de"
        db.session.commit()

        # Login as user
        with client.session_transaction() as sess:
            sess["_user_id"] = str(test_user.id)

        # Check that locale is set to user's preference
        with client.application.test_request_context():
            with client.session_transaction() as sess:
                # Simulate request context
                from flask import g
                from app import babel

                # The locale selector should return user's preference
                assert test_user.preferred_language == "de"

    def test_locale_from_session(self, client):
        """Test that locale is selected from session when not logged in"""
        with client:
            # Set language in session
            with client.session_transaction() as sess:
                sess["preferred_language"] = "fr"

            # Make a request
            response = client.get("/")

            # Check that session language is used
            with client.session_transaction() as sess:
                assert sess.get("preferred_language") == "fr"

    def test_locale_fallback_to_default(self, client):
        """Test that locale falls back to default when not set"""
        with client:
            # Don't set any language preference
            response = client.get("/")

            # Should use default locale (English)
            assert response.status_code in [200, 302]  # May redirect to login


class TestLanguageSwitching:
    """Test language switching functionality"""

    def test_set_language_direct_route(self, client, test_user):
        """Test direct language switching route"""
        # Login first
        with client.session_transaction() as sess:
            sess["_user_id"] = str(test_user.id)

        # Switch to Spanish
        response = client.get("/set-language/es", follow_redirects=False)

        # Should redirect
        assert response.status_code == 302

        # Check that user's preference is updated
        db.session.refresh(test_user)
        assert test_user.preferred_language == "es"

        # Check that session is updated
        with client.session_transaction() as sess:
            assert sess.get("preferred_language") == "es"

    def test_set_language_api_endpoint(self, client, test_user):
        """Test API endpoint for language switching"""
        # Login first
        with client.session_transaction() as sess:
            sess["_user_id"] = str(test_user.id)

        # Switch to Arabic via API
        response = client.post("/api/language", json={"language": "ar"}, content_type="application/json")

        assert response.status_code == 200
        data = response.get_json()
        assert data["success"] is True
        assert data["language"] == "ar"

        # Check that user's preference is updated
        db.session.refresh(test_user)
        assert test_user.preferred_language == "ar"

    def test_set_invalid_language(self, client, test_user):
        """Test that invalid languages are rejected"""
        # Login first
        with client.session_transaction() as sess:
            sess["_user_id"] = str(test_user.id)

        # Try to set invalid language
        response = client.post("/api/language", json={"language": "invalid"}, content_type="application/json")

        assert response.status_code == 400
        data = response.get_json()
        assert "error" in data

    def test_language_persists_across_sessions(self, client, test_user):
        """Test that language preference persists across sessions"""
        # Login and set language
        with client.session_transaction() as sess:
            sess["_user_id"] = str(test_user.id)
        client.get("/set-language/de", follow_redirects=True)

        # Logout
        client.get("/auth/logout", follow_redirects=True)

        # Login again
        with client.session_transaction() as sess:
            sess["_user_id"] = str(test_user.id)

        # Check that language preference is still set
        db.session.refresh(test_user)
        assert test_user.preferred_language == "de"


class TestRTLSupport:
    """Test Right-to-Left language support"""

    def test_rtl_detection_for_arabic(self, client, test_user):
        """Test that Arabic is detected as RTL"""
        # Set language to Arabic
        test_user.preferred_language = "ar"
        db.session.commit()

        # Login
        with client.session_transaction() as sess:
            sess["_user_id"] = str(test_user.id)

        # Get dashboard
        response = client.get("/dashboard")

        # Check that page includes RTL directive
        assert response.status_code == 200
        assert b'dir="rtl"' in response.data or b"dir='rtl'" in response.data

    def test_rtl_detection_for_hebrew(self, client, test_user):
        """Test that Hebrew is detected as RTL"""
        # Set language to Hebrew
        test_user.preferred_language = "he"
        db.session.commit()

        # Login
        with client.session_transaction() as sess:
            sess["_user_id"] = str(test_user.id)

        # Get dashboard
        response = client.get("/dashboard")

        # Check that page includes RTL directive
        assert response.status_code == 200
        assert b'dir="rtl"' in response.data or b"dir='rtl'" in response.data

    def test_ltr_for_english(self, client, test_user):
        """Test that English is LTR"""
        # Set language to English
        test_user.preferred_language = "en"
        db.session.commit()

        # Login
        with client.session_transaction() as sess:
            sess["_user_id"] = str(test_user.id)

        # Get dashboard
        response = client.get("/dashboard")

        # Check that page includes LTR directive
        assert response.status_code == 200
        assert b'dir="ltr"' in response.data or b"dir='ltr'" in response.data


class TestTranslations:
    """Test that translations are working"""

    def test_english_translations(self, client):
        """Test English translations"""
        with client.application.test_request_context():
            from flask_babel import _

            # Test common translations
            assert _("Dashboard") == "Dashboard"
            assert _("Projects") == "Projects"
            assert _("Login") == "Login"

    def test_translation_files_exist(self, client):
        """Test that translation files exist for all languages"""
        import os

        languages = ["en", "de", "fr", "es", "ar", "he", "nl", "it", "fi", "pt"]

        for lang in languages:
            po_file = os.path.join("translations", lang, "LC_MESSAGES", "messages.po")
            assert os.path.exists(po_file), f"Translation file missing for {lang}"


class TestLanguageSelectorUI:
    """Test language selector UI"""

    def test_language_selector_in_header(self, client, test_user):
        """Test that language selector appears in header"""
        # Login
        with client.session_transaction() as sess:
            sess["_user_id"] = str(test_user.id)

        # Get dashboard
        response = client.get("/dashboard")

        # Check that language selector is present
        assert response.status_code == 200
        assert b"langDropdown" in response.data or b"lang-dropdown" in response.data.lower()
        assert b"fa-globe" in response.data or b"globe" in response.data.lower()

    def test_language_list_contains_all_languages(self, client, test_user):
        """Test that language selector contains all available languages"""
        # Login
        with client.session_transaction() as sess:
            sess["_user_id"] = str(test_user.id)

        # Get dashboard
        response = client.get("/dashboard")
        assert response.status_code == 200
        response_text = response.data.decode("utf-8")

        # Check for language names in the page
        languages_to_check = ["English", "Español", "Français", "Deutsch"]
        for lang in languages_to_check:
            assert lang in response_text, f"Language '{lang}' not found in language selector"


class TestUserSettingsLanguage:
    """Test language settings in user settings page"""

    def test_language_setting_in_user_settings(self, client, test_user):
        """Test that language setting is available in user settings"""
        # Login
        with client.session_transaction() as sess:
            sess["_user_id"] = str(test_user.id)

        # Get settings page
        response = client.get("/settings")

        # Check that language setting is present
        assert response.status_code == 200
        assert b"preferred_language" in response.data or b"language" in response.data.lower()

    def test_save_language_in_user_settings(self, client, test_user):
        """Test saving language preference in user settings"""
        # Login
        with client.session_transaction() as sess:
            sess["_user_id"] = str(test_user.id)

        # Update settings with language
        response = client.post(
            "/settings",
            data={
                "preferred_language": "fr",
                "full_name": test_user.full_name or "Test User",
                "email": test_user.email or "test@example.com",
            },
            follow_redirects=True,
        )

        # Check that setting was saved
        assert response.status_code == 200
        db.session.refresh(test_user)
        assert test_user.preferred_language == "fr"


@pytest.fixture
def test_user(client):
    """Create a test user"""
    with client.application.app_context():
        user = User(username="testuser", role="user")
        user.is_active = True
        db.session.add(user)
        db.session.commit()
        yield user
        # Cleanup - delete related activities first to avoid constraint violations
        from app.models import Activity

        Activity.query.filter_by(user_id=user.id).delete()
        db.session.delete(user)
        db.session.commit()
