#!/usr/bin/env python3
"""
Debug test for Research API endpoints.

This test specifically helps debug issues with starting research via the API.
It can be run standalone to diagnose authentication, CSRF, and endpoint issues.
"""

import json
import requests
from bs4 import BeautifulSoup
import sys
import time


class ResearchAPIDebugTest:
    """Debug test suite for research API endpoints."""

    def __init__(self, base_url="http://localhost:5000"):
        self.base_url = base_url
        self.session = requests.Session()
        # Create unique username to avoid conflicts
        timestamp = int(time.time() * 1000)
        self.username = f"testuser_{timestamp}"
        self.password = "TestPass123"  # At least 8 characters

    def run_all_tests(self):
        """Run all debug tests."""
        print("=== Research API Debug Test ===")
        print(f"Base URL: {self.base_url}")
        print()

        # Test server connectivity
        if not self.test_server_connectivity():
            print("❌ Server is not running. Please start the server first.")
            return False

        # Test user registration if login fails
        if not self.test_authentication_flow():
            print("🔄 Authentication failed, trying to register user...")
            if not self.test_user_registration():
                print(
                    "❌ User registration failed. Cannot proceed with API tests."
                )
                return False

            # Try authentication again after registration
            if not self.test_authentication_flow():
                print("❌ Authentication still failed after registration.")
                return False

        # Test CSRF token handling
        if not self.test_csrf_tokens():
            print("❌ CSRF token handling failed.")
            return False

        # Test research API endpoints
        self.test_research_endpoints()

        return True

    def test_server_connectivity(self):
        """Test if server is running."""
        print("1. Testing server connectivity...")
        try:
            response = self.session.get(f"{self.base_url}/")
            print(f"   Status: {response.status_code}")
            if response.status_code == 200:
                print("   ✅ Server is running")
                return True
            print(f"   ❌ Server returned status {response.status_code}")
            return False
        except requests.exceptions.ConnectionError:
            print("   ❌ Cannot connect to server")
            return False
        except Exception as e:
            print(f"   ❌ Error: {e}")
            return False

    def test_user_registration(self):
        """Test user registration."""
        print("\n2b. Testing user registration...")

        try:
            # Get registration page
            register_page = self.session.get(f"{self.base_url}/auth/register")
            print(f"   Registration page status: {register_page.status_code}")

            if register_page.status_code != 200:
                print(
                    f"   ❌ Failed to get registration page: {register_page.text[:200]}"
                )
                return False

            # Extract CSRF token from registration page
            soup = BeautifulSoup(register_page.text, "html.parser")
            csrf_input = soup.find("input", {"name": "csrf_token"})
            register_csrf = csrf_input.get("value") if csrf_input else None

            if not register_csrf:
                print("   ❌ No CSRF token found in registration page")
                return False

            print(f"   Registration CSRF token: {register_csrf[:20]}...")

            # Attempt registration
            register_response = self.session.post(
                f"{self.base_url}/auth/register",
                data={
                    "username": self.username,
                    "password": self.password,
                    "confirm_password": self.password,  # Add confirmation field
                    "acknowledge": "true",  # Must acknowledge password recovery warning
                    "csrf_token": register_csrf,
                },
                allow_redirects=False,
            )

            print(
                f"   Registration response status: {register_response.status_code}"
            )

            if register_response.status_code in [200, 302]:
                print("   ✅ Registration successful")
                return True
            print(f"   ❌ Registration failed: {register_response.text[:200]}")
            return False

        except Exception as e:
            print(f"   ❌ Registration error: {e}")
            return False

    def test_authentication_flow(self):
        """Test login and authentication."""
        print("\n2. Testing authentication flow...")

        # Get login page (fresh page to ensure fresh CSRF token)
        try:
            login_page = self.session.get(f"{self.base_url}/auth/login")
            print(f"   Login page status: {login_page.status_code}")

            if login_page.status_code != 200:
                print(
                    f"   ❌ Failed to get login page: {login_page.text[:200]}"
                )
                return False

            # Extract CSRF token
            soup = BeautifulSoup(login_page.text, "html.parser")
            csrf_input = soup.find("input", {"name": "csrf_token"})
            login_csrf = csrf_input.get("value") if csrf_input else None

            if not login_csrf:
                print("   ❌ No CSRF token found in login page")
                return False

            print(f"   Login CSRF token: {login_csrf[:20]}...")

            # Attempt login
            login_response = self.session.post(
                f"{self.base_url}/auth/login",
                data={
                    "username": self.username,
                    "password": self.password,
                    "csrf_token": login_csrf,
                },
                allow_redirects=False,  # Don't follow redirects to see response clearly
            )

            print(f"   Login response status: {login_response.status_code}")

            if login_response.status_code in [200, 302]:
                print("   ✅ Login successful")
                return True
            print(f"   ❌ Login failed: {login_response.text[:200]}")
            return False

        except Exception as e:
            print(f"   ❌ Authentication error: {e}")
            return False

    def test_csrf_tokens(self):
        """Test CSRF token generation and usage."""
        print("\n3. Testing CSRF tokens...")

        try:
            # Get API CSRF token
            csrf_response = self.session.get(f"{self.base_url}/auth/csrf-token")
            print(f"   CSRF token endpoint status: {csrf_response.status_code}")

            if csrf_response.status_code != 200:
                print(
                    f"   ❌ Failed to get CSRF token: {csrf_response.text[:200]}"
                )
                return False

            csrf_data = csrf_response.json()
            csrf_token = csrf_data.get("csrf_token")

            if not csrf_token:
                print("   ❌ No CSRF token in response")
                return False

            print(f"   API CSRF token: {csrf_token[:20]}...")
            self.csrf_token = csrf_token
            return True

        except Exception as e:
            print(f"   ❌ CSRF token error: {e}")
            return False

    def test_research_endpoints(self):
        """Test research API endpoints."""
        print("\n4. Testing research API endpoints...")

        if not hasattr(self, "csrf_token"):
            print("   ❌ No CSRF token available")
            return

        # Prepare research request
        research_request = {
            "query": "What is machine learning?",
            "model": "gpt-4o-mini",  # Use a valid model name
            "search_engines": ["searxng"],
        }

        headers = {
            "X-CSRF-Token": self.csrf_token,
            "Content-Type": "application/json",
        }

        # Test 1: Correct endpoint /api/start_research
        print("\n   4a. Testing /api/start_research...")
        self._test_endpoint("/api/start_research", research_request, headers)

        # Test 2: Old endpoint /research/api/start
        print("\n   4b. Testing /research/api/start...")
        self._test_endpoint("/research/api/start", research_request, headers)

        # Test 3: Alternative endpoint /research/api/start_research
        print("\n   4c. Testing /research/api/start_research...")
        self._test_endpoint(
            "/research/api/start_research", research_request, headers
        )

        # Test 4: Check if user is properly authenticated for API
        print("\n   4d. Testing auth status...")
        self._test_auth_status()

    def _test_endpoint(self, endpoint, research_request, headers):
        """Test a specific research endpoint."""
        try:
            url = f"{self.base_url}{endpoint}"
            response = self.session.post(
                url, json=research_request, headers=headers
            )

            print(f"       Endpoint: {endpoint}")
            print(f"       Status: {response.status_code}")
            print(f"       Response: {response.text[:300]}")

            if response.status_code == 200:
                try:
                    data = response.json()
                    if data.get("status") == "success":
                        research_id = data.get("research_id")
                        print("       ✅ Research started successfully!")
                        print(f"       Research ID: {research_id}")

                        # Test research status
                        self._test_research_status(research_id)
                    elif data.get("status") == "queued":
                        print("       ✅ Research queued successfully!")
                        print(
                            f"       Queue position: {data.get('queue_position')}"
                        )
                    else:
                        print(
                            f"       ⚠️  Research returned: {data.get('status', 'unknown')}"
                        )
                except json.JSONDecodeError:
                    print("       ⚠️  Response is not valid JSON")
            elif response.status_code == 401:
                print("       ❌ Authentication failed for this endpoint")
            elif response.status_code == 403:
                print("       ❌ Forbidden - CSRF token issue")
            elif response.status_code == 404:
                print("       ❌ Endpoint not found")
            elif response.status_code == 500:
                print("       ❌ Server error - check logs")
            else:
                print("       ⚠️  Unexpected status code")

        except Exception as e:
            print(f"       ❌ Error testing endpoint: {e}")

    def _test_research_status(self, research_id):
        """Test getting research status."""
        if not research_id:
            return

        try:
            # Wait a moment for research to initialize
            time.sleep(1)  # allow: unmarked-sleep

            status_url = f"{self.base_url}/api/research/{research_id}/status"
            response = self.session.get(status_url)

            print(f"       Status check: {response.status_code}")
            if response.status_code == 200:
                data = response.json()
                print(
                    f"       Research status: {data.get('status', 'unknown')}"
                )
                print(f"       Progress: {data.get('progress', 0)}%")
            else:
                print(f"       Status check failed: {response.text[:100]}")

        except Exception as e:
            print(f"       Error checking status: {e}")

    def _test_auth_status(self):
        """Test authentication status."""
        try:
            response = self.session.get(f"{self.base_url}/auth/check")
            print(f"       Auth check status: {response.status_code}")

            if response.status_code == 200:
                data = response.json()
                print(
                    f"       Authenticated: {data.get('authenticated', False)}"
                )
                print(f"       Username: {data.get('username', 'None')}")
                print(f"       Session cookies: {len(self.session.cookies)}")
            else:
                print(f"       Auth check failed: {response.text[:100]}")

        except Exception as e:
            print(f"       Error checking auth: {e}")


def main():
    """Run the debug test."""
    import argparse

    parser = argparse.ArgumentParser(description="Debug Research API endpoints")
    parser.add_argument(
        "--url", default="http://localhost:5000", help="Base URL for the server"
    )
    parser.add_argument(
        "--username", default="admin", help="Username for authentication"
    )
    parser.add_argument(
        "--password", default="admin", help="Password for authentication"
    )

    args = parser.parse_args()

    # Create and run test
    test = ResearchAPIDebugTest(args.url)
    test.username = args.username
    test.password = args.password

    success = test.run_all_tests()

    if success:
        print("\n✅ Debug tests completed successfully")
        sys.exit(0)
    else:
        print("\n❌ Debug tests failed")
        sys.exit(1)


if __name__ == "__main__":
    main()
