#!/usr/bin/env python3
"""
CLI interface for WebQuiz Testing System.

Usage:
    webquiz           # Start server in foreground
    webquiz -d        # Start server as daemon
    webquiz --daemon  # Start server as daemon
    webquiz --help    # Show help
"""

import argparse
import sys
import os
import subprocess
import signal
import time
import webbrowser
from pathlib import Path
import asyncio
from aiohttp import web

# Enable coverage tracking for subprocesses only when COVERAGE_PROCESS_START is set
if os.environ.get("COVERAGE_PROCESS_START"):
    try:
        import coverage

        coverage.process_startup()
    except ImportError:
        pass  # Coverage not installed, skip

from .server import create_app, load_config_with_overrides


def get_pid_file_path():
    """Get the path to the PID file."""
    return Path.cwd() / "webquiz.pid"


def is_daemon_running():
    """Check if daemon is already running."""
    pid_file = get_pid_file_path()
    if not pid_file.exists():
        return False

    try:
        with open(pid_file, "r") as f:
            pid = int(f.read().strip())

        # Check if process is still running
        os.kill(pid, 0)  # This will raise OSError if process doesn't exist
        return True
    except (OSError, ValueError, FileNotFoundError):
        # Process is not running, remove stale PID file
        if pid_file.exists():
            pid_file.unlink()
        return False


def start_daemon():
    """Start the server as a daemon process."""
    if is_daemon_running():
        print("❌ Daemon is already running")
        return 1

    print("🚀 Starting webquiz daemon...")

    # Fork the process
    try:
        pid = os.fork()
        if pid > 0:
            # Parent process
            # Wait a moment to check if child started successfully
            time.sleep(1)
            if is_daemon_running():
                print(f"✅ Daemon started successfully (PID: {pid})")
                print(f"🌐 Server running at http://0.0.0.0:8080 (accessible on network)")
                print(f"📄 Logs: server.log")
                print(f"⏹️  Stop with: kill {pid}")
                return 0
            else:
                print("❌ Failed to start daemon")
                return 1
        else:
            # Child process - become daemon
            os.setsid()  # Create new session

            # Fork again to ensure we're not session leader
            pid = os.fork()
            if pid > 0:
                os._exit(0)

            # Write PID file
            with open(get_pid_file_path(), "w") as f:
                f.write(str(os.getpid()))

            # Redirect standard file descriptors
            with open("/dev/null", "r") as f:
                os.dup2(f.fileno(), sys.stdin.fileno())

            # Keep stdout/stderr for now (they'll go to server.log anyway)

            # Change working directory to avoid holding locks
            os.chdir("/")

            # Set signal handlers for graceful shutdown
            def signal_handler(signum, frame):
                pid_file = get_pid_file_path()
                if pid_file.exists():
                    pid_file.unlink()
                sys.exit(0)

            signal.signal(signal.SIGTERM, signal_handler)
            signal.signal(signal.SIGINT, signal_handler)

            # Start the server
            try:
                # Get config from global variable set in main()
                config = getattr(start_daemon, "_config", None)
                if config is None:
                    from .server import WebQuizConfig

                    config = WebQuizConfig()
                run_server(config)
            except Exception as e:
                print(f"❌ Error starting server: {e}")
                pid_file = get_pid_file_path()
                if pid_file.exists():
                    pid_file.unlink()
                sys.exit(1)

    except OSError as e:
        print(f"❌ Fork failed: {e}")
        return 1


def stop_daemon():
    """Stop the daemon process."""
    if not is_daemon_running():
        print("❌ No daemon is running")
        return 1

    pid_file = get_pid_file_path()
    try:
        with open(pid_file, "r") as f:
            pid = int(f.read().strip())

        print(f"⏹️  Stopping daemon (PID: {pid})...")
        os.kill(pid, signal.SIGTERM)

        # Wait for process to stop
        for _ in range(10):  # Wait up to 10 seconds
            time.sleep(1)
            if not is_daemon_running():
                print("✅ Daemon stopped successfully")
                return 0

        # Force kill if still running
        print("⚠️  Force killing daemon...")
        os.kill(pid, signal.SIGKILL)
        pid_file.unlink()
        print("✅ Daemon force stopped")
        return 0

    except (OSError, ValueError, FileNotFoundError) as e:
        print(f"❌ Error stopping daemon: {e}")
        return 1


def run_server(config):
    """Run the server in foreground mode."""
    print("🚀 Starting WebQuiz Testing System...")
    print(f"📁 Quizzes directory: {config.paths.quizzes_dir}")
    print(f"📝 Logs directory: {config.paths.logs_dir}")
    print(f"📊 CSV directory: {config.paths.csv_dir}")
    print(f"📂 Static directory: {config.paths.static_dir}")
    print(f"🔑 Master key: {'Set' if config.admin.master_key else 'Not set (admin disabled)'}")
    print(f"🌐 Server will be available at: http://{config.server.host}:{config.server.port} (accessible on network)")
    if config.admin.master_key:
        print(f"🔧 Admin panel: http://{config.server.host}:{config.server.port}/admin")
    print("⏹️  Press Ctrl+C to stop")

    async def start_server():
        app = await create_app(config)
        runner = web.AppRunner(app)
        await runner.setup()

        site = web.TCPSite(runner, config.server.host, config.server.port)
        await site.start()

        print("✅ Server started successfully")

        # Open browser for admin interface if running as binary
        if os.environ.get("WEBQUIZ_IS_BINARY") == "1":
            admin_url = f"http://127.0.0.1:{config.server.port}/admin/"
            print(f"🌐 Opening admin interface: {admin_url}")
            try:
                webbrowser.open(admin_url)
            except Exception as e:
                print(f"⚠️  Could not open browser: {e}")

        try:
            # Keep the server running
            while True:
                await asyncio.sleep(1)
        except KeyboardInterrupt:
            print("\n⏹️  Shutting down server...")
        finally:
            await runner.cleanup()

    try:
        asyncio.run(start_server())
    except KeyboardInterrupt:
        print("✅ Server stopped")
    except Exception as e:
        print(f"❌ Error: {e}")
        return 1

    return 0


def main():
    """Main CLI entry point."""
    parser = argparse.ArgumentParser(
        prog="webquiz",
        description="WebQuiz - A modern web-based quiz and testing platform",
        formatter_class=argparse.RawDescriptionHelpFormatter,
        epilog="""
Examples:
  webquiz                              Start server with defaults
  webquiz -d                           Start server as daemon
  webquiz --config server.yaml        Use configuration file
  webquiz --quizzes-dir my_quizzes     Use custom quizzes directory
  webquiz --master-key secret123       Set admin master key
  webquiz --logs-dir /var/log          Use custom logs directory
  webquiz --csv-dir /data              Use custom CSV directory
  webquiz --static /var/www/quiz       Use custom static files directory
  WEBQUIZ_MASTER_KEY=secret webquiz    Set master key via environment
  webquiz --config prod.yaml --master-key override  Mix config file with CLI overrides
  webquiz --stop                       Stop daemon server
  webquiz --status                     Check daemon status

The server will be available at http://0.0.0.0:8080 (accessible on network)
Quiz files loaded from quizzes/ directory (auto-created if missing)
Admin panel available at http://0.0.0.0:8080/admin (if master key is set)
User responses saved to data/{quiz_name}_user_responses_{suffix}.csv
Server logs written to logs/server_{suffix}.log
Static files served from static/ directory
CLI parameters always override config file values
        """,
    )

    parser.add_argument("-d", "--daemon", action="store_true", help="Run server as daemon in background")

    parser.add_argument("--stop", action="store_true", help="Stop daemon server")

    parser.add_argument("--status", action="store_true", help="Check daemon status")

    parser.add_argument("--config", help="Path to YAML configuration file")

    parser.add_argument("--quizzes-dir", help="Path to quizzes directory (default: quizzes)")

    parser.add_argument("--master-key", help="Master key for admin access (can also use WEBQUIZ_MASTER_KEY env var)")

    parser.add_argument("--logs-dir", help="Directory for log files (default: logs/)")

    parser.add_argument("--csv-dir", help="Directory for CSV response files (default: data/)")

    parser.add_argument("--static", help="Path to static files directory (default: static)")

    parser.add_argument("--version", action="version", version=f"%(prog)s 1.0.0")

    args = parser.parse_args()

    # Load configuration with CLI overrides
    config = load_config_with_overrides(
        config_path=args.config,
        quizzes_dir=args.quizzes_dir,
        master_key=args.master_key,
        logs_dir=args.logs_dir,
        csv_dir=args.csv_dir,
        static_dir=args.static,
    )

    # Handle daemon stop
    if args.stop:
        return stop_daemon()

    # Handle status check
    if args.status:
        if is_daemon_running():
            pid_file = get_pid_file_path()
            with open(pid_file, "r") as f:
                pid = f.read().strip()
            print(f"✅ Daemon is running (PID: {pid})")
            print(f"🌐 Server: http://0.0.0.0:8080 (accessible on network)")
            return 0
        else:
            print("❌ Daemon is not running")
            return 1

    # Handle daemon start
    if args.daemon:
        # Store config for daemon process
        start_daemon._config = config
        return start_daemon()

    # Default: run server in foreground
    return run_server(config)


if __name__ == "__main__":
    sys.exit(main())
