#!/usr/bin/env python3
"""
Comprehensive test runner for Tritri application
Runs backend API tests, frontend tests, and integration tests
"""

import subprocess
import sys
import time
import os
import requests
from pathlib import Path

def run_command(command, cwd=None, check=True):
    """Run a command and return the result"""
    print(f"🔄 Running: {' '.join(command)}")
    try:
        result = subprocess.run(
            command,
            cwd=cwd,
            check=check,
            capture_output=False,
            text=True
        )
        print(f"✅ Command completed successfully")
        return result
    except subprocess.CalledProcessError as e:
        print(f"❌ Command failed with exit code {e.returncode}")
        if not check:
            return e
        sys.exit(1)

def wait_for_api(timeout=30):
    """Wait for the API to be ready"""
    print("⏳ Waiting for API to be ready...")
    start_time = time.time()

    while time.time() - start_time < timeout:
        try:
            response = requests.get("http://localhost:8000/health", timeout=5)
            if response.status_code == 200:
                print("✅ API is ready")
                return True
        except requests.RequestException:
            pass

        time.sleep(1)
        print(f"   Still waiting... ({int(time.time() - start_time)}s)")

    print("❌ API failed to start within timeout")
    return False

def check_dependencies():
    """Check if required dependencies are available"""
    print("🔍 Checking dependencies...")

    # Check Python
    try:
        python_version = subprocess.run([sys.executable, "--version"], capture_output=True, text=True)
        print(f"   Python: {python_version.stdout.strip()}")
    except FileNotFoundError:
        print("❌ Python not found")
        return False

    # Check Node.js
    try:
        node_version = subprocess.run(["node", "--version"], capture_output=True, text=True)
        print(f"   Node.js: {node_version.stdout.strip()}")
    except FileNotFoundError:
        print("❌ Node.js not found")
        return False

    # Check npm
    try:
        npm_version = subprocess.run(["npm", "--version"], capture_output=True, text=True)
        print(f"   npm: {npm_version.stdout.strip()}")
    except FileNotFoundError:
        print("❌ npm not found")
        return False

    print("✅ All dependencies found")
    return True

def setup_backend():
    """Setup backend environment"""
    print("🔧 Setting up backend...")

    backend_dir = Path("backend")
    if not backend_dir.exists():
        print("❌ Backend directory not found")
        return False

    # Install dependencies
    run_command([sys.executable, "-m", "pip", "install", "-r", "requirements.txt"], cwd=backend_dir)

    print("✅ Backend setup complete")
    return True

def setup_frontend():
    """Setup frontend environment"""
    print("🔧 Setting up frontend...")

    frontend_dir = Path("frontend")
    if not frontend_dir.exists():
        print("❌ Frontend directory not found")
        return False

    # Install dependencies
    run_command(["npm", "install"], cwd=frontend_dir)

    print("✅ Frontend setup complete")
    return True

def run_backend_tests():
    """Run backend API tests"""
    print("\n🧪 Running Backend Tests...")

    backend_dir = Path("backend")

    # Run different test suites
    test_suites = [
        ("Basic API Tests", "tests/test_api.py"),
        ("Expense Tests", "backend/tests/test_expenses.py"),
        ("Currency Tests", "backend/tests/test_currency.py"),
        ("Export Tests", "backend/tests/test_export.py")
    ]

    all_passed = True
    for suite_name, test_file in test_suites:
        print(f"\n   📋 Running {suite_name}...")
        try:
            if test_file.startswith("backend/"):
                # Run with pytest
                result = subprocess.run([
                    sys.executable, "-m", "pytest",
                    test_file, "-v", "--tb=short"
                ], cwd=".", capture_output=True, text=True)
            else:
                # Run with python directly
                result = subprocess.run([
                    sys.executable, test_file
                ], cwd=".", capture_output=True, text=True)

            if result.returncode == 0:
                print(f"   ✅ {suite_name} passed")
                if result.stdout:
                    print(f"      {result.stdout.strip()}")
            else:
                print(f"   ❌ {suite_name} failed")
                if result.stderr:
                    print(f"      Error: {result.stderr.strip()}")
                all_passed = False

        except Exception as e:
            print(f"   ❌ {suite_name} failed with exception: {e}")
            all_passed = False

    return all_passed

def run_frontend_tests():
    """Run frontend tests"""
    print("\n🧪 Running Frontend Tests...")

    frontend_dir = Path("frontend")

    # Check if frontend is built
    if not (frontend_dir / ".next").exists():
        print("   📦 Building frontend...")
        run_command(["npm", "run", "build"], cwd=frontend_dir)

    # Run Playwright tests
    try:
        result = subprocess.run([
            "npm", "run", "test"
        ], cwd=frontend_dir, capture_output=True, text=True)

        if result.returncode == 0:
            print("✅ Frontend tests passed")
            return True
        else:
            print("❌ Frontend tests failed")
            if result.stdout:
                print(f"Output: {result.stdout}")
            if result.stderr:
                print(f"Error: {result.stderr}")
            return False

    except Exception as e:
        print(f"❌ Frontend tests failed with exception: {e}")
        return False

def run_integration_tests():
    """Run integration tests"""
    print("\n🧪 Running Integration Tests...")

    integration_tests = [
        "test_integration.py",
        "test_e2e_user_flow.py",
        "test_trip_creator_access.py"
    ]

    all_passed = True
    for test_file in integration_tests:
        if Path(test_file).exists():
            print(f"   📋 Running {test_file}...")
            try:
                result = subprocess.run([
                    sys.executable, test_file
                ], capture_output=True, text=True)

                if result.returncode == 0:
                    print(f"   ✅ {test_file} passed")
                else:
                    print(f"   ❌ {test_file} failed")
                    if result.stderr:
                        print(f"      Error: {result.stderr.strip()}")
                    all_passed = False
            except Exception as e:
                print(f"   ❌ {test_file} failed with exception: {e}")
                all_passed = False
        else:
            print(f"   ⚠️ {test_file} not found, skipping")

    return all_passed

def generate_test_report():
    """Generate a test coverage report"""
    print("\n📊 Generating Test Report...")

    # This could be expanded to generate HTML reports, coverage reports, etc.
    report = {
        "timestamp": time.strftime("%Y-%m-%d %H:%M:%S"),
        "features_tested": [
            "Trip creation and management",
            "Multi-trip identity system",
            "Expense tracking with percentage splitting",
            "Currency conversion with real-time rates",
            "Data export (CSV/JSON)",
            "Analytics dashboard",
            "Share functionality",
            "Participant management",
            "Responsive design",
            "API validation and error handling"
        ],
        "test_types": [
            "Unit tests (backend services)",
            "API endpoint tests",
            "Frontend component tests",
            "End-to-end user flow tests",
            "Integration tests"
        ]
    }

    print("✅ Test Report Generated:")
    print(f"   Timestamp: {report['timestamp']}")
    print(f"   Features Tested: {len(report['features_tested'])}")
    print(f"   Test Types: {len(report['test_types'])}")

    return report

def main():
    """Main test runner"""
    print("🚀 Tritri Comprehensive Test Suite")
    print("=" * 50)

    # Check dependencies
    if not check_dependencies():
        sys.exit(1)

    # Setup environments
    if not setup_backend():
        sys.exit(1)

    if not setup_frontend():
        sys.exit(1)

    # Run tests
    results = {
        "backend": False,
        "frontend": False,
        "integration": False
    }

    # Start API for tests that need it
    print("\n🔄 Starting API server for tests...")
    api_process = subprocess.Popen([
        sys.executable, "-m", "uvicorn",
        "app.main:app", "--host", "0.0.0.0", "--port", "8000"
    ], cwd="backend")

    try:
        # Wait for API to be ready
        if wait_for_api():
            # Run backend tests
            results["backend"] = run_backend_tests()

            # Run integration tests
            results["integration"] = run_integration_tests()
        else:
            print("❌ Skipping tests that require API")
    finally:
        # Stop API server
        api_process.terminate()
        api_process.wait()
        print("🛑 API server stopped")

    # Run frontend tests (these don't need the API server running)
    results["frontend"] = run_frontend_tests()

    # Generate report
    report = generate_test_report()

    # Summary
    print("\n" + "=" * 50)
    print("📋 TEST SUMMARY")
    print("=" * 50)

    for test_type, passed in results.items():
        status = "✅ PASSED" if passed else "❌ FAILED"
        print(f"{test_type.capitalize():<12}: {status}")

    all_passed = all(results.values())

    if all_passed:
        print("\n🎉 ALL TESTS PASSED!")
        print("✅ Tritri application is ready for production")
    else:
        print("\n❌ SOME TESTS FAILED!")
        print("⚠️ Please review the failing tests and fix issues")
        sys.exit(1)

if __name__ == "__main__":
    main()