from __future__ import annotations

import argparse
import sys
from datetime import datetime

from .app import RunSummaryTUI, SecureCheckTUI
from .catalog import builtin_scenarios, task_catalog
from .config import build_paths, ensure_app_dirs
from .executor import ExecutionContext, execute_tasks
from .logging_utils import attach_run_handler, setup_logging
from .status import collect_status
from .storage import ScenarioStore
from .system_info import detect_system


def parse_args() -> argparse.Namespace:
    parser = argparse.ArgumentParser(description="SecureCheck - console semi-graphique pour contrôles sécurité Linux")
    parser.add_argument("--dry-run", action="store_true", help="Simule les commandes sans modifier le système")
    parser.add_argument("--run", action="store_true", help="Lance immédiatement les tâches passées via --tasks ou --scenario")
    parser.add_argument("--tasks", help="Liste de tâches séparées par des virgules")
    parser.add_argument("--scenario", help="Nom d'un scénario enregistré ou builtin")
    parser.add_argument("--list-scenarios", action="store_true", help="Affiche les scénarios disponibles")
    return parser.parse_args()


def resolve_task_selection(args: argparse.Namespace, store: ScenarioStore, available_task_keys: set[str]) -> list[str]:
    if args.scenario:
        scenario = store.get(args.scenario)
        if not scenario:
            raise SystemExit(f"Scénario inconnu: {args.scenario}")
        return [key for key in scenario.task_keys if key in available_task_keys]

    if args.tasks:
        selected = [key.strip() for key in args.tasks.split(",") if key.strip()]
        invalid = [key for key in selected if key not in available_task_keys]
        if invalid:
            raise SystemExit(f"Tâches inconnues: {', '.join(invalid)}")
        return selected

    return []


def print_led_dashboard(system) -> None:
    print("")
    print("=== Etat du système ===")
    for item in collect_status(system):
        led = "\033[32m●\033[0m" if item.ok else "\033[31m●\033[0m"
        print(f"{led} [{item.category}] {item.label}: {item.detail}")


def print_summary(results, run_log_path, system) -> None:
    ok_count = sum(1 for result in results if result.success)
    ko_count = len(results) - ok_count
    print("")
    print("=== Résumé ===")
    for result in results:
        status = "OK" if result.success else "ECHEC"
        suffix = f" | erreur: {result.error}" if result.error else ""
        print(f"- {status} | {result.label} | {result.duration_seconds:.1f}s{suffix}")
        for detail in result.details:
            print(f"  {detail}")
    print_led_dashboard(system)
    print(f"Logs d'exécution: {run_log_path}")
    print(f"Total OK={ok_count} / ECHEC={ko_count}")


def main() -> int:
    args = parse_args()
    paths = build_paths()
    ensure_app_dirs(paths)
    logger = setup_logging(paths.app_log_file)
    system = detect_system()

    tasks = task_catalog()
    task_by_key = {task.key: task for task in tasks}
    store = ScenarioStore(paths.scenario_file, builtin_scenarios())

    if args.list_scenarios:
        for scenario in store.list_all():
            print(f"{scenario.name}: {scenario.description}")
        return 0

    selected_keys = resolve_task_selection(args, store, set(task_by_key))
    interactive_mode = not args.run
    active_scenario_name = args.scenario
    menu_message: str | None = None

    while True:
        if interactive_mode:
            tui = SecureCheckTUI(
                system,
                tasks,
                store,
                status_provider=lambda: collect_status(system),
                initial_selected=set(selected_keys) if selected_keys else None,
                initial_scenario_name=active_scenario_name,
                initial_message=menu_message,
            )
            selection = tui.run()
            if selection is None:
                return 0
            selected_keys = selection.task_keys
            active_scenario_name = selection.scenario_name

        if not selected_keys:
            if interactive_mode:
                menu_message = "Aucune tâche sélectionnée."
                continue
            print("Aucune tâche sélectionnée.")
            return 1

        selected_tasks = [task_by_key[key] for key in selected_keys]
        context = ExecutionContext(paths=paths, system=system, logger=logger, dry_run=args.dry_run)

        run_log_path = paths.log_dir / f"run-{datetime.now().strftime('%Y%m%d-%H%M%S')}.log"
        run_handler = attach_run_handler(logger, run_log_path)
        try:
            results = execute_tasks(context, selected_tasks)
        finally:
            logger.removeHandler(run_handler)
            run_handler.close()

        if interactive_mode:
            status_items = collect_status(system)
            RunSummaryTUI(results, status_items, str(run_log_path)).run()
            ok_count = sum(1 for result in results if result.success)
            ko_count = len(results) - ok_count
            menu_message = f"Dernière exécution: {ok_count} OK / {ko_count} ECHEC. Sélection prête pour une nouvelle action."
            continue

        print_summary(results, run_log_path, system)
        return 0 if all(result.success for result in results) else 2


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