import os
import asyncio
from pathlib import Path
import sys
import argparse
from zscams.agent.src.support.configuration import RemoteConfig, config, CONFIG_PATH
from zscams.agent.src.support.filesystem import is_file_exists, resolve_path
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.backend.client import backend_client
from zscams.agent.src.support.logger import get_logger


logger = get_logger("tls_tunnel_main")


def init_parser():
    parser = argparse.ArgumentParser(description="ZSCAMs Agent")
    parser.add_argument(
        "--bootstrap",
        action="store_true",
        help="Run bootstrap process and exit",
    )
    parser.add_argument(
        "--rebootstrap",
        action="store_true",
        help="Run unbootstrap and then the bootstrap processes and exit",
    )
    parser.add_argument(
        "--unbootstrap",
        action="store_true",
        help="Run unbootstrap process and exit",
    )
    parser.add_argument(
        "--update-machine-info",
        action="store_true",
        help="Reinitialize machine info",
    )
    return parser


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

    custom_config_path = Path(config.get("config_dir", must_resolve=True))
    files_to_ensure = [
        custom_config_path.joinpath(config.get("remote.ca_cert", must_resolve=True)),
        custom_config_path.joinpath(
            config.get("remote.client_cert", must_resolve=True)
        ),
        custom_config_path.joinpath(config.get("remote.client_key", must_resolve=True)),
    ]

    missing_files = []

    for file in files_to_ensure:
        if not is_file_exists(file, logger):
            missing_files.append(file)

    bootstrapped = backend_client.is_bootstrapped()

    if not bootstrapped or missing_files:
        logger.debug("Agent has entry on server: %s", bootstrapped)
        logger.debug(
            "Missing files: %s",
            ", ".join(missing_files) if missing_files else "No missing files",
        )
        logger.error(
            "Agent is not bootstrapped. Please run `zscams --bootstrap` to start the bootstrap process.",
        )
        sys.exit(1)


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

    custom_config_dir = Path(config.get("config_dir", must_resolve=True))

    ssl_context = create_ssl_context(
        config.get("remote", valtyp=RemoteConfig), custom_config_dir
    )
    remote_host = config.get("remote.host")
    remote_port = config.get("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
    config_dir = os.path.dirname(CONFIG_PATH)
    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)
