#!/Users/stwhite/CODE/chatterbox-ui/.venv/bin/python
"""
Startup script that launches both the backend and frontend servers concurrently.
"""

import os
import sys
import time
import signal
import subprocess
import threading
from pathlib import Path

# Try to load environment variables, but don't fail if dotenv is not available
try:
    from dotenv import load_dotenv

    load_dotenv()
except ImportError:
    print("python-dotenv not installed, using system environment variables only")

# Configuration
BACKEND_PORT = int(os.getenv("BACKEND_PORT", "8000"))
BACKEND_HOST = os.getenv("BACKEND_HOST", "0.0.0.0")
# Frontend host/port (for dev server binding)
FRONTEND_PORT = int(os.getenv("FRONTEND_PORT", "8001"))
FRONTEND_HOST = os.getenv("FRONTEND_HOST", "0.0.0.0")

# Export frontend host/port so backend CORS config can pick them up automatically
os.environ["FRONTEND_HOST"] = FRONTEND_HOST
os.environ["FRONTEND_PORT"] = str(FRONTEND_PORT)

# Get project root directory
PROJECT_ROOT = Path(__file__).parent.absolute()


def run_backend():
    """Run the backend FastAPI server"""
    os.chdir(PROJECT_ROOT / "backend")
    cmd = [
        sys.executable,
        "-m",
        "uvicorn",
        "app.main:app",
        "--reload",
        f"--host={BACKEND_HOST}",
        f"--port={BACKEND_PORT}",
    ]

    print(f"\n{'='*50}")
    print(f"Starting Backend Server at http://{BACKEND_HOST}:{BACKEND_PORT}")
    print(f"API docs available at http://{BACKEND_HOST}:{BACKEND_PORT}/docs")
    print(f"{'='*50}\n")

    return subprocess.Popen(
        cmd,
        stdout=subprocess.PIPE,
        stderr=subprocess.STDOUT,
        universal_newlines=True,
        bufsize=1,
    )


def run_frontend():
    """Run the frontend development server"""
    frontend_dir = PROJECT_ROOT / "frontend"
    os.chdir(frontend_dir)

    cmd = [sys.executable, "start_dev_server.py"]
    env = os.environ.copy()
    env["VITE_DEV_SERVER_HOST"] = FRONTEND_HOST
    env["VITE_DEV_SERVER_PORT"] = str(FRONTEND_PORT)

    print(f"\n{'='*50}")
    print(f"Starting Frontend Server at http://{FRONTEND_HOST}:{FRONTEND_PORT}")
    print(f"{'='*50}\n")

    return subprocess.Popen(
        cmd,
        env=env,
        stdout=subprocess.PIPE,
        stderr=subprocess.STDOUT,
        universal_newlines=True,
        bufsize=1,
    )


def print_process_output(process, prefix):
    """Print process output with a prefix"""
    for line in iter(process.stdout.readline, ""):
        if not line:
            break
        print(f"{prefix} | {line}", end="")


def main():
    """Main function to start both servers"""
    print("\n🚀 Starting Chatterbox UI Development Environment")

    # Start the backend server
    backend_process = run_backend()

    # Give the backend a moment to start
    time.sleep(2)

    # Start the frontend server
    frontend_process = run_frontend()

    # Create threads to monitor and print output
    backend_monitor = threading.Thread(
        target=print_process_output, args=(backend_process, "BACKEND"), daemon=True
    )
    frontend_monitor = threading.Thread(
        target=print_process_output, args=(frontend_process, "FRONTEND"), daemon=True
    )

    backend_monitor.start()
    frontend_monitor.start()

    # Setup signal handling for graceful shutdown
    def signal_handler(sig, frame):
        print("\n\n🛑 Shutting down servers...")
        backend_process.terminate()
        frontend_process.terminate()
        # Threads are daemon, so they'll exit when the main thread exits
        print("✅ Servers stopped successfully")
        sys.exit(0)

    signal.signal(signal.SIGINT, signal_handler)

    # Print access information
    print("\n📋 Access Information:")
    print(f"  • Frontend: http://{FRONTEND_HOST}:{FRONTEND_PORT}")
    print(f"  • Backend API: http://{BACKEND_HOST}:{BACKEND_PORT}/api")
    print(f"  • API Documentation: http://{BACKEND_HOST}:{BACKEND_PORT}/docs")
    print("\n⚠️  Press Ctrl+C to stop both servers\n")

    # Keep the main process running
    try:
        while True:
            time.sleep(1)
    except KeyboardInterrupt:
        signal_handler(None, None)


if __name__ == "__main__":
    main()
