"""Regression tests for the Floating AI's Universal Multilingual + Translation Engine.

What we lock in:
  1. The system prompt actually carries the LANGUAGE & TRANSLATION ENGINE block.
  2. An explicit "translate ... to ..." command emits the strict 3-line
     **Source:** / **Target:** / **Translated:** format.
  3. Multi-target ("Hindi AND Marathi") returns two blocks separated by `---`.
  4. Domain keywords (GST, Purchase, Invoice, UPI) are preserved as English even
     when translating into a foreign language target.
  5. Normal conversation in any Indian language does NOT trigger Translation Mode
     (i.e. the assistant does NOT emit the Source/Target/Translated block).

These are live LLM tests — they hit Emergent's universal-LLM key. We keep them
tolerant: each test only asserts the contract markers, not the exact wording.
"""
import os
import re
import pytest

BASE_URL = os.environ.get("REACT_APP_BACKEND_URL", "https://offline-billing-pro-2.preview.emergentagent.com").rstrip("/")


@pytest.mark.timeout(90)
class TestAiTranslationEngine:
    # ---- 1. System constant carries the new policy ------------------------
    def test_multilingual_engine_constant_present(self):
        """The MULTILINGUAL_ENGINE block must exist and mention key rules."""
        import importlib
        mod = importlib.import_module("ai_assistant")
        text = getattr(mod, "MULTILINGUAL_ENGINE", "")
        assert text, "MULTILINGUAL_ENGINE constant missing"
        # Core sections must be present
        assert "LANGUAGE AUTO-DETECTION" in text
        assert "TRANSLATION MODE" in text
        assert "**Source:**" in text and "**Target:**" in text and "**Translated:**" in text
        # Must mention keyword preservation
        assert "GST" in text and "Invoice" in text and "Purchase" in text
        # Must forbid code fences
        assert "code fence" in text.lower() or "backtick" in text.lower()

    # ---- 2. Explicit translation → 3-line Source/Target/Translated -------
    def test_translation_mode_hindi_to_english(self, admin_session):
        r = admin_session.post(
            f"{BASE_URL}/api/ai/chat",
            json={
                "message": "Translate this to English: मेरा आज का sale invoice tayar karo",
                "company_id": "",
                "session_id": "test-translate-hi-en",
            },
            timeout=60,
        )
        assert r.status_code == 200, r.text
        reply = r.json().get("reply", "")
        assert "**Source:**" in reply, f"Missing Source label: {reply[:300]}"
        assert "**Target:**" in reply, f"Missing Target label: {reply[:300]}"
        assert "**Translated:**" in reply, f"Missing Translated label: {reply[:300]}"
        # Should NOT be wrapped in triple-backtick code fences
        assert not reply.lstrip().startswith("```"), f"Output should not be code-fenced: {reply[:120]}"

    # ---- 3. Multi-target translation block separator ---------------------
    def test_translation_multi_target_separator(self, admin_session):
        r = admin_session.post(
            f"{BASE_URL}/api/ai/chat",
            json={
                "message": "Translate \"Today's sale is ₹50,000\" to Hindi AND Marathi",
                "company_id": "",
                "session_id": "test-translate-multi",
            },
            timeout=60,
        )
        assert r.status_code == 200, r.text
        reply = r.json().get("reply", "")
        # Two Source/Target/Translated blocks expected
        assert reply.count("**Source:**") >= 2, f"Expected 2+ Source blocks: {reply[:400]}"
        assert reply.count("**Target:**") >= 2, f"Expected 2+ Target blocks: {reply[:400]}"
        # Separator between blocks
        assert "---" in reply, f"Missing --- separator: {reply[:400]}"

    # ---- 4. Domain keywords survive foreign-language translation ---------
    def test_translation_preserves_business_keywords_french(self, admin_session):
        r = admin_session.post(
            f"{BASE_URL}/api/ai/chat",
            json={
                "message": "Translate \"naya purchase bill banao aur GST 18% lagao\" to French",
                "company_id": "",
                "session_id": "test-translate-keywords",
            },
            timeout=60,
        )
        assert r.status_code == 200, r.text
        reply = r.json().get("reply", "")
        # Must be in Translation Mode
        assert "**Translated:**" in reply, f"Not in Translation Mode: {reply[:300]}"
        # Pull just the "Translated:" payload and assert it contains GST and
        # some form of "Purchase" — not the French equivalents.
        m = re.search(r"\*\*Translated:\*\*\s*(.+)", reply, re.DOTALL)
        translated = (m.group(1) if m else reply).lower()
        assert "gst" in translated, f"GST keyword localised away: {translated[:300]}"
        assert "purchase" in translated, f"Purchase keyword localised away: {translated[:300]}"

    # ---- 5. Normal conversation does NOT trigger Translation Mode --------
    def test_normal_conversation_no_translation_block(self, admin_session):
        r = admin_session.post(
            f"{BASE_URL}/api/ai/chat",
            json={
                "message": "कमी स्टॉक मधे कोणत्या items आहेत?",  # Marathi
                "company_id": "",
                "session_id": "test-conv-marathi",
            },
            timeout=60,
        )
        assert r.status_code == 200, r.text
        reply = r.json().get("reply", "")
        # No structured translation block in casual conversation
        assert "**Source:**" not in reply, f"Translation Mode wrongly triggered: {reply[:300]}"
        assert "**Target:**" not in reply, f"Translation Mode wrongly triggered: {reply[:300]}"
