#!/usr/bin/env python3
"""Backend test suite for Randevu chat/AI endpoints."""
import requests
import sys
import json
from typing import Optional, Dict, Any

# Base URL from frontend/.env
BASE_URL = "https://highlight-docs-2.preview.emergentagent.com/api"

# Admin credentials
ADMIN_USERNAME = "admin"
ADMIN_PASSWORD = "Randevu2025!"

# Global state
auth_token: Optional[str] = None
saved_session_id: Optional[str] = None


def log_test(name: str, passed: bool, details: str = "") -> None:
    """Log test result."""
    status = "✅ PASS" if passed else "❌ FAIL"
    print(f"{status}: {name}")
    if details:
        print(f"  → {details}")


def login() -> bool:
    """Login and get bearer token."""
    global auth_token
    try:
        resp = requests.post(
            f"{BASE_URL}/admin/login",
            json={"username": ADMIN_USERNAME, "password": ADMIN_PASSWORD},
            timeout=10
        )
        if resp.status_code != 200:
            log_test("Admin login", False, f"Status {resp.status_code}: {resp.text}")
            return False
        
        data = resp.json()
        if "access_token" not in data:
            log_test("Admin login", False, "No access_token in response")
            return False
        
        auth_token = data["access_token"]
        log_test("Admin login", True, f"Token received, username={data.get('username')}")
        return True
    except Exception as e:
        log_test("Admin login", False, str(e))
        return False


def get_auth_headers() -> Dict[str, str]:
    """Get authorization headers."""
    return {"Authorization": f"Bearer {auth_token}"} if auth_token else {}


def test_new_session() -> bool:
    """Test 1: New session (no session_id)."""
    global saved_session_id
    try:
        resp = requests.post(
            f"{BASE_URL}/public/chat/message",
            json={"message": "Salam, hansı xidmətlər var?"},
            timeout=30
        )
        
        if resp.status_code != 200:
            log_test("New session (no session_id)", False, f"Status {resp.status_code}: {resp.text}")
            return False
        
        data = resp.json()
        
        # Check required fields
        if "session_id" not in data:
            log_test("New session (no session_id)", False, "Missing session_id in response")
            return False
        
        if "user_message" not in data or not isinstance(data["user_message"], dict):
            log_test("New session (no session_id)", False, "Missing or invalid user_message")
            return False
        
        if "ai_message" not in data:
            log_test("New session (no session_id)", False, "Missing ai_message field")
            return False
        
        # Validate user_message structure
        user_msg = data["user_message"]
        if not all(k in user_msg for k in ["id", "role", "content"]):
            log_test("New session (no session_id)", False, f"user_message missing required fields: {user_msg}")
            return False
        
        if user_msg["role"] != "user":
            log_test("New session (no session_id)", False, f"user_message role is '{user_msg['role']}', expected 'user'")
            return False
        
        # Validate ai_message (should be dict with role='assistant' and non-empty content)
        ai_msg = data["ai_message"]
        if ai_msg is None:
            log_test("New session (no session_id)", False, "ai_message is null (AI might be disabled)")
            return False
        
        if not isinstance(ai_msg, dict):
            log_test("New session (no session_id)", False, f"ai_message is not a dict: {type(ai_msg)}")
            return False
        
        if ai_msg.get("role") != "assistant":
            log_test("New session (no session_id)", False, f"ai_message role is '{ai_msg.get('role')}', expected 'assistant'")
            return False
        
        if not ai_msg.get("content") or not ai_msg["content"].strip():
            log_test("New session (no session_id)", False, "ai_message content is empty")
            return False
        
        # Save session_id for next tests
        saved_session_id = data["session_id"]
        
        log_test(
            "New session (no session_id)", 
            True, 
            f"session_id={saved_session_id}, user_msg_id={user_msg['id']}, ai_content_length={len(ai_msg['content'])}"
        )
        return True
        
    except Exception as e:
        log_test("New session (no session_id)", False, str(e))
        return False


def test_multi_turn() -> bool:
    """Test 2: Multi-turn conversation."""
    if not saved_session_id:
        log_test("Multi-turn conversation", False, "No saved_session_id from previous test")
        return False
    
    try:
        resp = requests.post(
            f"{BASE_URL}/public/chat/message",
            json={"session_id": saved_session_id, "message": "İlk sualımı yenidən söylə"},
            timeout=30
        )
        
        if resp.status_code != 200:
            log_test("Multi-turn conversation", False, f"Status {resp.status_code}: {resp.text}")
            return False
        
        data = resp.json()
        
        # Check session_id matches
        if data.get("session_id") != saved_session_id:
            log_test("Multi-turn conversation", False, f"session_id mismatch: got {data.get('session_id')}, expected {saved_session_id}")
            return False
        
        # Check ai_message is non-empty
        ai_msg = data.get("ai_message")
        if not ai_msg or not isinstance(ai_msg, dict):
            log_test("Multi-turn conversation", False, "ai_message is null or not a dict")
            return False
        
        if not ai_msg.get("content") or not ai_msg["content"].strip():
            log_test("Multi-turn conversation", False, "ai_message content is empty")
            return False
        
        log_test("Multi-turn conversation", True, f"Same session_id, ai_content_length={len(ai_msg['content'])}")
        return True
        
    except Exception as e:
        log_test("Multi-turn conversation", False, str(e))
        return False


def test_get_session() -> bool:
    """Test 3: Get session messages."""
    if not saved_session_id:
        log_test("Get session messages", False, "No saved_session_id")
        return False
    
    try:
        resp = requests.get(
            f"{BASE_URL}/public/chat/session/{saved_session_id}",
            timeout=10
        )
        
        if resp.status_code != 200:
            log_test("Get session messages", False, f"Status {resp.status_code}: {resp.text}")
            return False
        
        data = resp.json()
        
        if data.get("session_id") != saved_session_id:
            log_test("Get session messages", False, f"session_id mismatch")
            return False
        
        if "messages" not in data or not isinstance(data["messages"], list):
            log_test("Get session messages", False, "Missing or invalid messages array")
            return False
        
        messages = data["messages"]
        if len(messages) < 4:  # Should have at least 2 user + 2 assistant messages
            log_test("Get session messages", False, f"Expected at least 4 messages, got {len(messages)}")
            return False
        
        # Verify messages are ordered by createdAt
        created_ats = [m.get("createdAt", "") for m in messages]
        if created_ats != sorted(created_ats):
            log_test("Get session messages", False, "Messages not ordered by createdAt")
            return False
        
        log_test("Get session messages", True, f"Retrieved {len(messages)} messages, ordered correctly")
        return True
        
    except Exception as e:
        log_test("Get session messages", False, str(e))
        return False


def test_empty_message() -> bool:
    """Test 4: Empty message validation."""
    try:
        resp = requests.post(
            f"{BASE_URL}/public/chat/message",
            json={"message": ""},
            timeout=10
        )
        
        if resp.status_code != 400:
            log_test("Empty message validation", False, f"Expected 400, got {resp.status_code}")
            return False
        
        log_test("Empty message validation", True, "Correctly returns 400 for empty message")
        return True
        
    except Exception as e:
        log_test("Empty message validation", False, str(e))
        return False


def test_admin_chats_no_auth() -> bool:
    """Test 5a: GET /admin/chats without auth."""
    try:
        resp = requests.get(f"{BASE_URL}/admin/chats", timeout=10)
        
        if resp.status_code != 401:
            log_test("GET /admin/chats without auth", False, f"Expected 401, got {resp.status_code}")
            return False
        
        log_test("GET /admin/chats without auth", True, "Correctly returns 401")
        return True
        
    except Exception as e:
        log_test("GET /admin/chats without auth", False, str(e))
        return False


def test_admin_chats_with_auth() -> bool:
    """Test 5b: GET /admin/chats with auth."""
    if not saved_session_id:
        log_test("GET /admin/chats with auth", False, "No saved_session_id")
        return False
    
    try:
        resp = requests.get(
            f"{BASE_URL}/admin/chats",
            headers=get_auth_headers(),
            timeout=10
        )
        
        if resp.status_code != 200:
            log_test("GET /admin/chats with auth", False, f"Status {resp.status_code}: {resp.text}")
            return False
        
        data = resp.json()
        if not isinstance(data, list):
            log_test("GET /admin/chats with auth", False, "Response is not a list")
            return False
        
        # Check if our saved_session_id is in the list
        session_ids = [s.get("id") for s in data]
        if saved_session_id not in session_ids:
            log_test("GET /admin/chats with auth", False, f"saved_session_id {saved_session_id} not in list")
            return False
        
        # Validate structure of first session
        if data:
            session = data[0]
            required_fields = ["id", "visitor_name", "createdAt", "lastActivity", "message_count", "last_message"]
            missing = [f for f in required_fields if f not in session]
            if missing:
                log_test("GET /admin/chats with auth", False, f"Missing fields: {missing}")
                return False
        
        log_test("GET /admin/chats with auth", True, f"Retrieved {len(data)} sessions, saved_session_id found")
        return True
        
    except Exception as e:
        log_test("GET /admin/chats with auth", False, str(e))
        return False


def test_admin_chat_detail() -> bool:
    """Test 5c: GET /admin/chats/{id} with auth."""
    if not saved_session_id:
        log_test("GET /admin/chats/{id} with auth", False, "No saved_session_id")
        return False
    
    try:
        resp = requests.get(
            f"{BASE_URL}/admin/chats/{saved_session_id}",
            headers=get_auth_headers(),
            timeout=10
        )
        
        if resp.status_code != 200:
            log_test("GET /admin/chats/{id} with auth", False, f"Status {resp.status_code}: {resp.text}")
            return False
        
        data = resp.json()
        
        if "session" not in data or "messages" not in data:
            log_test("GET /admin/chats/{id} with auth", False, "Missing session or messages field")
            return False
        
        if not isinstance(data["messages"], list):
            log_test("GET /admin/chats/{id} with auth", False, "messages is not a list")
            return False
        
        log_test("GET /admin/chats/{id} with auth", True, f"Retrieved session with {len(data['messages'])} messages")
        return True
        
    except Exception as e:
        log_test("GET /admin/chats/{id} with auth", False, str(e))
        return False


def test_admin_chat_nonexistent() -> bool:
    """Test 5d: GET /admin/chats/nonexistent-id with auth."""
    try:
        resp = requests.get(
            f"{BASE_URL}/admin/chats/nonexistent-id-12345",
            headers=get_auth_headers(),
            timeout=10
        )
        
        if resp.status_code != 404:
            log_test("GET /admin/chats/nonexistent-id with auth", False, f"Expected 404, got {resp.status_code}")
            return False
        
        log_test("GET /admin/chats/nonexistent-id with auth", True, "Correctly returns 404")
        return True
        
    except Exception as e:
        log_test("GET /admin/chats/nonexistent-id with auth", False, str(e))
        return False


def test_admin_reply() -> bool:
    """Test 5e: POST /admin/chats/{id}/message with auth."""
    if not saved_session_id:
        log_test("POST /admin/chats/{id}/message with auth", False, "No saved_session_id")
        return False
    
    try:
        resp = requests.post(
            f"{BASE_URL}/admin/chats/{saved_session_id}/message",
            json={"message": "Bu admin cavabıdır"},
            headers=get_auth_headers(),
            timeout=10
        )
        
        if resp.status_code != 200:
            log_test("POST /admin/chats/{id}/message with auth", False, f"Status {resp.status_code}: {resp.text}")
            return False
        
        data = resp.json()
        
        if data.get("role") != "admin":
            log_test("POST /admin/chats/{id}/message with auth", False, f"Expected role='admin', got '{data.get('role')}'")
            return False
        
        if data.get("content") != "Bu admin cavabıdır":
            log_test("POST /admin/chats/{id}/message with auth", False, f"Content mismatch")
            return False
        
        log_test("POST /admin/chats/{id}/message with auth", True, f"Admin message added with id={data.get('id')}")
        return True
        
    except Exception as e:
        log_test("POST /admin/chats/{id}/message with auth", False, str(e))
        return False


def test_admin_message_in_session() -> bool:
    """Test 5f: Verify admin message appears in GET /public/chat/session/{id}."""
    if not saved_session_id:
        log_test("Verify admin message in session", False, "No saved_session_id")
        return False
    
    try:
        resp = requests.get(
            f"{BASE_URL}/public/chat/session/{saved_session_id}",
            timeout=10
        )
        
        if resp.status_code != 200:
            log_test("Verify admin message in session", False, f"Status {resp.status_code}: {resp.text}")
            return False
        
        data = resp.json()
        messages = data.get("messages", [])
        
        # Find admin message
        admin_messages = [m for m in messages if m.get("role") == "admin"]
        if not admin_messages:
            log_test("Verify admin message in session", False, "No admin messages found")
            return False
        
        # Check if our message is there
        admin_contents = [m.get("content") for m in admin_messages]
        if "Bu admin cavabıdır" not in admin_contents:
            log_test("Verify admin message in session", False, "Admin message content not found")
            return False
        
        log_test("Verify admin message in session", True, f"Admin message found in session")
        return True
        
    except Exception as e:
        log_test("Verify admin message in session", False, str(e))
        return False


def test_ai_disable() -> bool:
    """Test 6a: Disable AI via settings."""
    try:
        resp = requests.put(
            f"{BASE_URL}/admin/settings/ai_enabled",
            json={"value": "false"},
            headers=get_auth_headers(),
            timeout=10
        )
        
        if resp.status_code != 200:
            log_test("Disable AI via settings", False, f"Status {resp.status_code}: {resp.text}")
            return False
        
        data = resp.json()
        if data.get("key") != "ai_enabled" or data.get("value") != "false":
            log_test("Disable AI via settings", False, f"Unexpected response: {data}")
            return False
        
        log_test("Disable AI via settings", True, "ai_enabled set to false")
        return True
        
    except Exception as e:
        log_test("Disable AI via settings", False, str(e))
        return False


def test_ai_disabled_response() -> bool:
    """Test 6b: POST message with AI disabled."""
    try:
        resp = requests.post(
            f"{BASE_URL}/public/chat/message",
            json={"message": "Test mesajı AI söndürülüb"},
            timeout=10
        )
        
        if resp.status_code != 200:
            log_test("POST message with AI disabled", False, f"Status {resp.status_code}: {resp.text}")
            return False
        
        data = resp.json()
        
        # ai_message should be null when AI is disabled
        if data.get("ai_message") is not None:
            log_test("POST message with AI disabled", False, f"ai_message should be null, got: {data.get('ai_message')}")
            return False
        
        log_test("POST message with AI disabled", True, "ai_message is null as expected")
        return True
        
    except Exception as e:
        log_test("POST message with AI disabled", False, str(e))
        return False


def test_ai_enable() -> bool:
    """Test 6c: Re-enable AI via settings."""
    try:
        resp = requests.put(
            f"{BASE_URL}/admin/settings/ai_enabled",
            json={"value": "true"},
            headers=get_auth_headers(),
            timeout=10
        )
        
        if resp.status_code != 200:
            log_test("Re-enable AI via settings", False, f"Status {resp.status_code}: {resp.text}")
            return False
        
        data = resp.json()
        if data.get("key") != "ai_enabled" or data.get("value") != "true":
            log_test("Re-enable AI via settings", False, f"Unexpected response: {data}")
            return False
        
        log_test("Re-enable AI via settings", True, "ai_enabled set to true")
        return True
        
    except Exception as e:
        log_test("Re-enable AI via settings", False, str(e))
        return False


def test_ai_enabled_response() -> bool:
    """Test 6d: POST message with AI enabled again."""
    try:
        resp = requests.post(
            f"{BASE_URL}/public/chat/message",
            json={"message": "Test mesajı AI yenidən aktivdir"},
            timeout=30
        )
        
        if resp.status_code != 200:
            log_test("POST message with AI enabled", False, f"Status {resp.status_code}: {resp.text}")
            return False
        
        data = resp.json()
        
        # ai_message should be non-null when AI is enabled
        ai_msg = data.get("ai_message")
        if ai_msg is None:
            log_test("POST message with AI enabled", False, "ai_message is null (should be non-null)")
            return False
        
        if not isinstance(ai_msg, dict) or not ai_msg.get("content"):
            log_test("POST message with AI enabled", False, f"ai_message invalid: {ai_msg}")
            return False
        
        log_test("POST message with AI enabled", True, f"ai_message is non-null, content_length={len(ai_msg['content'])}")
        return True
        
    except Exception as e:
        log_test("POST message with AI enabled", False, str(e))
        return False


def test_delete_chat() -> bool:
    """Test 7: DELETE /admin/chats/{id} with auth."""
    if not saved_session_id:
        log_test("DELETE /admin/chats/{id} with auth", False, "No saved_session_id")
        return False
    
    try:
        resp = requests.delete(
            f"{BASE_URL}/admin/chats/{saved_session_id}",
            headers=get_auth_headers(),
            timeout=10
        )
        
        if resp.status_code != 200:
            log_test("DELETE /admin/chats/{id} with auth", False, f"Status {resp.status_code}: {resp.text}")
            return False
        
        data = resp.json()
        if data.get("status") != "ok":
            log_test("DELETE /admin/chats/{id} with auth", False, f"Expected status=ok, got {data}")
            return False
        
        log_test("DELETE /admin/chats/{id} with auth", True, "Session deleted successfully")
        return True
        
    except Exception as e:
        log_test("DELETE /admin/chats/{id} with auth", False, str(e))
        return False


def test_deleted_chat_404() -> bool:
    """Test 7b: Verify deleted chat returns 404."""
    if not saved_session_id:
        log_test("Verify deleted chat returns 404", False, "No saved_session_id")
        return False
    
    try:
        resp = requests.get(
            f"{BASE_URL}/admin/chats/{saved_session_id}",
            headers=get_auth_headers(),
            timeout=10
        )
        
        if resp.status_code != 404:
            log_test("Verify deleted chat returns 404", False, f"Expected 404, got {resp.status_code}")
            return False
        
        log_test("Verify deleted chat returns 404", True, "Correctly returns 404 after deletion")
        return True
        
    except Exception as e:
        log_test("Verify deleted chat returns 404", False, str(e))
        return False


def main():
    """Run all tests."""
    print("=" * 80)
    print("RANDEVU BACKEND - CHAT/AI ENDPOINTS TEST SUITE")
    print("=" * 80)
    print()
    
    # Login first
    if not login():
        print("\n❌ Login failed, cannot proceed with tests")
        sys.exit(1)
    
    print()
    
    # Run all tests
    tests = [
        ("1. New session (no session_id)", test_new_session),
        ("2. Multi-turn conversation", test_multi_turn),
        ("3. Get session messages", test_get_session),
        ("4. Empty message validation", test_empty_message),
        ("5a. GET /admin/chats without auth", test_admin_chats_no_auth),
        ("5b. GET /admin/chats with auth", test_admin_chats_with_auth),
        ("5c. GET /admin/chats/{id} with auth", test_admin_chat_detail),
        ("5d. GET /admin/chats/nonexistent-id", test_admin_chat_nonexistent),
        ("5e. POST /admin/chats/{id}/message", test_admin_reply),
        ("5f. Verify admin message in session", test_admin_message_in_session),
        ("6a. Disable AI via settings", test_ai_disable),
        ("6b. POST message with AI disabled", test_ai_disabled_response),
        ("6c. Re-enable AI via settings", test_ai_enable),
        ("6d. POST message with AI enabled", test_ai_enabled_response),
        ("7a. DELETE /admin/chats/{id}", test_delete_chat),
        ("7b. Verify deleted chat returns 404", test_deleted_chat_404),
    ]
    
    passed = 0
    failed = 0
    
    for name, test_func in tests:
        try:
            if test_func():
                passed += 1
            else:
                failed += 1
        except Exception as e:
            log_test(name, False, f"Unexpected error: {e}")
            failed += 1
        print()
    
    # Summary
    print("=" * 80)
    print(f"TEST SUMMARY: {passed} passed, {failed} failed out of {passed + failed} total")
    print("=" * 80)
    
    if failed > 0:
        sys.exit(1)
    else:
        print("\n✅ All tests passed!")
        sys.exit(0)


if __name__ == "__main__":
    main()
