"""Отладочная командная утилита для запуска пайплайна без API."""

from __future__ import annotations

import argparse
import asyncio
import json
import logging
import sys
from collections.abc import Iterable

from ioc_checker.analysis import run_indicator_analysis
from ioc_checker.config import configure_logging
from ioc_checker.iocs import identify_ioc
from ioc_checker.main import parse_text
from ioc_checker.providers.features import build_provider_features
from ioc_checker.queue import get_task, queue
from ioc_checker.services import (
    DuplicateTaskError,
    MissingTokenError,
    NoIocsProvidedError,
    enqueue_task,
)
from ioc_checker.startup import bootstrap, shutdown

logger = logging.getLogger(__name__)


def _build_parser() -> argparse.ArgumentParser:
    """Создать парсер аргументов командной строки."""

    parser = argparse.ArgumentParser(
        description="Запустить полный цикл обработки IOC без HTTP API.",
    )
    parser.add_argument(
        "text",
        help="Текст, содержащий IOC для постановки на проверку",
    )
    return parser


def _flatten_matches(matches: dict[str, list[str]]) -> list[str]:
    """Преобразовать сгруппированные IOC в плоский список без повторов."""

    flat: list[str] = []
    seen: set[str] = set()
    for values in matches.values():
        for candidate in values:
            if candidate not in seen:
                seen.add(candidate)
                flat.append(candidate)
    return flat


def _print_matches(matches: dict[str, list[str]]) -> None:
    """Вывести найденные IOC в сгруппированном виде."""

    print("Найденные IOC:")
    if not matches:
        print("  (ничего не обнаружено)")
        return
    for bucket, values in matches.items():
        print(f"  {bucket}:")
        for value in values:
            print(f"    - {value}")


async def _print_results(task_id: str) -> None:
    """Отобразить результаты работы провайдеров и итоговый статус."""

    task = get_task(task_id)
    if task is None:
        print("Задание не найдено в памяти, результаты недоступны")
        return
    print()
    print(f"Статус задания {task_id}: {task.status}")
    if task.error:
        print(f"Ошибка: {task.error}")
    for indicator_value, provider_results in task.results.items():
        print()
        print(f"IOC: {indicator_value}")
        for provider_name, payload in provider_results.items():
            print(f"  Провайдер {provider_name}:")
            if payload is False:
                print("    - ошибка или пустой ответ")
                payload = {}
            formatted = json.dumps(payload, ensure_ascii=False, indent=2, default=str)
            for line in formatted.splitlines():
                print(f"    {line}")

        indicator = identify_ioc(indicator_value)
        precomputed_analysis = (task.verdicts or {}).get(indicator_value)
        if precomputed_analysis:
            analysis_result = dict(precomputed_analysis)
            provider_features = analysis_result.get("features") or {}
        else:
            provider_features = build_provider_features(indicator, provider_results)
            analysis_result = await run_indicator_analysis(indicator, provider_features)

        print("  Фичи провайдеров:")
        if not provider_features:
            print("    - не удалось построить фичи")
        for provider_name, features in provider_features.items():
            print(f"    {provider_name}:")
            formatted_features = json.dumps(
                features, ensure_ascii=False, indent=2, default=str
            )
            for line in formatted_features.splitlines():
                print(f"      {line}")

        print("  Результат анализа:")
        formatted_analysis = json.dumps(
            analysis_result, ensure_ascii=False, indent=2, default=str
        )
        for line in formatted_analysis.splitlines():
            print(f"    {line}")


async def _process(text: str) -> int:
    """Асинхронная точка входа утилиты."""

    configure_logging()
    logger.info("Инициализация инфраструктуры приложения")
    await bootstrap()
    try:
        logger.info("Разбор входного текста длиной %d символов", len(text))
        matches = await parse_text(text)
        _print_matches(matches)
        iocs = _flatten_matches(matches)
        if not iocs:
            logger.error("Текст не содержит поддерживаемых IOC")
            return 1
        logger.info("Постановка %d IOC на обработку", len(iocs))
        try:
            task_response = await enqueue_task(text)
        except MissingTokenError as exc:
            logger.error("Отсутствует токен для провайдера %s", exc.provider)
            return 1
        except DuplicateTaskError as exc:
            logger.error("Задание %s уже существует", exc.task_id)
            return 1
        except NoIocsProvidedError:
            logger.error("Не удалось сформировать список IOC для обработки")
            return 1
        task_id = task_response["task"]["id"]
        logger.info("Задание %s поставлено в очередь", task_id)
        await queue.join()
        logger.info("Задание %s завершено, формирование отчёта", task_id)
        await _print_results(task_id)
        return 0
    finally:
        logger.info("Завершение работы, остановка воркеров")
        await shutdown()


def main(argv: Iterable[str] | None = None) -> int:
    """Синхронная точка входа."""

    arguments = list(sys.argv[1:] if argv is None else argv)
    parser = _build_parser()
    args = parser.parse_args(arguments)
    try:
        return asyncio.run(
                _process(
                    args.text,
                )
        )
    except KeyboardInterrupt:
        logger.warning("Выполнение прервано пользователем")
        return 130


if __name__ == "__main__":  # pragma: no cover - защищаем запуск как скрипта
    raise SystemExit(main())
