"""
Main entry point for ZSCAMs Agent
"""

import os
import asyncio
import sys
import argparse
from zscams.agent.src.core.api.backend.bootstrap import bootstrap
from zscams.agent.src.core.api.backend.update_machine_info import update_machine_info
from zscams.agent.src.support.configuration import get_config, CONFIG_PATH
from zscams.agent.src.support.logger import get_logger
from zscams.agent.src.core.tunnel.tls import create_ssl_context
from zscams.agent.src.core.tunnels import start_all_tunnels
from zscams.agent.src.core.services import start_all_services
from zscams.agent.src.core.service_health_check import monitor_services
from zscams.agent.src.core.api.backend.client import backend_client

logger = get_logger("tls_tunnel_main")


def ensure_bootstrapped():
    """Ensure the agent is bootstrapped with the backend."""

    bootstrapped = backend_client.is_bootstrapped()
    logger.debug("Agent bootstrapped: %s", bootstrapped)
    if not bootstrapped:
        logger.error(
            "Agent is not bootstrapped. Please run `zscams --bootstrap` to start the bootstrap process.",
        )
        sys.exit(1)


async def async_main():
    """Asynchronous main function to start tunnels and services."""

    config = get_config()
    config_dir = os.path.dirname(CONFIG_PATH)
    ssl_context = create_ssl_context(config["remote"], config_dir=config_dir)
    remote_host = config["remote"]["host"]
    remote_port = config["remote"]["port"]

    # Start tunnels and wait for readiness
    tunnel_tasks = await start_all_tunnels(
        config.get("forwards", []), remote_host, remote_port, ssl_context
    )

    # Start services that depend on tunnels
    service_tasks = asyncio.create_task(
        start_all_services(config.get("services", []), config_dir=config_dir)
    )

    # Start health checks
    monitor_task = asyncio.create_task(
        monitor_services(
            config.get("services", []),
            config_dir=config_dir,
            interval=config.get("general", {}).get("health_check_interval", 300),
        )
    )

    logger.info("[*] All tunnels and services started. Press Ctrl+C to stop.")
    await asyncio.gather(*tunnel_tasks, service_tasks, monitor_task)


def main():
    """Main function to run the asynchronous main."""
    parser = argparse.ArgumentParser(description="ZSCAMs Agent")
    parser.add_argument(
        "--bootstrap",
        action="store_true",
        help="Run bootstrap process and exit",
    )
    parser.add_argument(
        "--update-machine-info",
        action="store_true",
        help="Run bootstrap process and exit",
    )
    args = parser.parse_args()

    if args.bootstrap:
        try:
            bootstrap()
            sys.exit(0)
        except Exception as exception:
            logger.error(exception)
            sys.exit(1)

    if args.update_machine_info:
        update_machine_info()
        sys.exit(0)

    try:
        ensure_bootstrapped()
        asyncio.run(async_main())
    except KeyboardInterrupt:
        logger.info("Exiting TLS Tunnel Client")


if __name__ == "__main__":
    main()
