from gvm.connections import UnixSocketConnection
from gvm.protocols.gmp import Gmp
from gvm.errors import GvmError
from src.utils.logger import get_logger

logger = get_logger("openvas_scanner")

class OpenvasScanner:
    def __init__(self, socket_path='/var/lib/docker/volumes/greenbone-community-edition_gvmd_socket_vol/_data/gvmd.sock'):
        """
        Инициализация сканера OpenVAS.

        :param socket_path: Путь к сокету GVM (по умолчанию '/var/run/gvmd.sock')
        """
        self.socket_path = socket_path
        self.connection = None
        self.gmp = None

    def connect(self, username, password):
        """
        Подключение к GVM.

        :param username: Имя пользователя для аутентификации
        :param password: Пароль для аутентификации
        """
        try:
            self.connection = UnixSocketConnection(path=self.socket_path)
            with Gmp(connection=self.connection) as gmp:
                gmp.authenticate(username, password)
            logger.info(f"Успешно подключено к GVM через {self.socket_path}")
        except GvmError as e:
            logger.error(f"Ошибка подключения к GVM: {e}")
            raise

    def get_configurations(self):
        """
        Получение списка конфигураций сканирования.

        :return: Список названий конфигураций
        """
        try:
            configs = self.gmp.get_scan_configs()
            return [config.get('name') for config in configs]
        except GvmError as e:
            logger.error(f"Ошибка при получении конфигураций: {e}")
            raise

    def create_target(self, name, hosts):
        """
        Создание цели для сканирования.

        :param name: Имя цели
        :param hosts: Список хостов (IP-адресов или сетей)
        :return: ID созданной цели
        """
        try:
            target = self.gmp.create_target(name=name, hosts=hosts)
            return target.get('id')
        except GvmError as e:
            logger.error(f"Ошибка при создании цели: {e}")
            raise

    def create_task(self, name, config_name, target_id):
        """
        Создание задачи сканирования.

        :param name: Имя задачи
        :param config_name: Название конфигурации сканирования
        :param target_id: ID цели
        :return: ID созданной задачи
        """
        try:
            configs = self.gmp.get_scan_configs(filter=f"name={config_name}")
            if not configs:
                raise ValueError(f"Конфигурация '{config_name}' не найдена")
            config_id = configs[0].get('id')
            task = self.gmp.create_task(name=name, config_id=config_id, target_id=target_id)
            return task.get('id')
        except GvmError as e:
            logger.error(f"Ошибка при создании задачи: {e}")
            raise

    def start_task(self, task_id):
        """
        Запуск задачи сканирования.

        :param task_id: ID задачи
        """
        try:
            self.gmp.start_task(task_id)
            logger.info(f"Задача {task_id} запущена")
        except GvmError as e:
            logger.error(f"Ошибка при запуске задачи: {e}")
            raise

    def get_task_status(self, task_id):
        """
        Получение статуса задачи.

        :param task_id: ID задачи
        :return: Статус задачи
        """
        try:
            task = self.gmp.get_task(task_id)
            return task.get('status')
        except GvmError as e:
            logger.error(f"Ошибка при получении статуса задачи: {e}")
            raise

    def get_report(self, task_id):
        """
        Получение отчета по задаче.

        :param task_id: ID задачи
        :return: Отчет в формате XML
        """
        try:
            reports = self.gmp.get_reports(filter=f"task_id={task_id}")
            if reports:
                report_id = reports[0].get('id')
                report = self.gmp.get_report(report_id, format='xml')
                return report
            return None
        except GvmError as e:
            logger.error(f"Ошибка при получении отчета: {e}")
            raise