"""Vulnerability Service - 漏洞资产业务逻辑层"""

import logging
from typing import List, Optional

from apps.asset.models import Vulnerability
from apps.asset.dtos.asset import VulnerabilityDTO
from apps.common.decorators import auto_ensure_db_connection
from apps.common.utils import deduplicate_for_bulk
from apps.common.utils.filter_utils import apply_filters

logger = logging.getLogger(__name__)


@auto_ensure_db_connection
class VulnerabilityService:
    """漏洞资产服务

    当前提供基础的批量创建能力，使用 ignore_conflicts 依赖数据库唯一约束去重。
    """
    
    # 智能过滤字段映射
    FILTER_FIELD_MAPPING = {
        'type': 'vuln_type',
        'severity': 'severity',
        'source': 'source',
        'url': 'url',
    }

    def bulk_create_ignore_conflicts(self, items: List[VulnerabilityDTO]) -> None:
        """批量创建漏洞资产记录，忽略冲突。

        注意：会自动按 (target_id, url, vuln_type, source) 去重，保留最后一条记录。

        Note:
            - 是否去重取决于模型上的唯一/部分唯一约束；
            - 当前 Vulnerability 模型未定义唯一约束，因此会保留全部记录。
        """
        if not items:
            logger.debug("漏洞资产列表为空，跳过保存")
            return

        try:
            # 根据模型唯一约束自动去重（如果模型没有唯一约束则跳过）
            unique_items = deduplicate_for_bulk(items, Vulnerability)
            
            vulns = [
                Vulnerability(
                    target_id=item.target_id,
                    url=item.url,
                    vuln_type=item.vuln_type,
                    severity=item.severity,
                    source=item.source,
                    cvss_score=item.cvss_score,
                    description=item.description,
                    raw_output=item.raw_output,
                )
                for item in unique_items
            ]

            Vulnerability.objects.bulk_create(vulns, ignore_conflicts=True)
            logger.info("漏洞资产保存成功 - 数量: %d", len(vulns))

        except Exception as e:
            logger.error(
                "批量保存漏洞资产失败 - 数量: %d, 错误: %s",
                len(items),
                str(e),
                exc_info=True,
            )
            raise

    # ==================== 查询方法 ====================

    def get_all(self, filter_query: Optional[str] = None):
        """获取所有漏洞 QuerySet（用于全局漏洞列表）。

        Args:
            filter_query: 智能过滤语法字符串

        Returns:
            QuerySet[Vulnerability]: 所有漏洞，按创建时间倒序
        """
        queryset = Vulnerability.objects.all().order_by("-created_at")
        if filter_query:
            queryset = apply_filters(queryset, filter_query, self.FILTER_FIELD_MAPPING)
        return queryset

    def get_vulnerabilities_by_target(self, target_id: int, filter_query: Optional[str] = None):
        """按目标获取漏洞 QuerySet（用于分页）。

        Args:
            target_id: 目标 ID
            filter_query: 智能过滤语法字符串

        Returns:
            QuerySet[Vulnerability]: 目标下的所有漏洞，按创建时间倒序
        """
        queryset = Vulnerability.objects.filter(target_id=target_id).order_by("-created_at")
        if filter_query:
            queryset = apply_filters(queryset, filter_query, self.FILTER_FIELD_MAPPING)
        return queryset

    def count_by_target(self, target_id: int) -> int:
        """统计目标下的漏洞数量。"""
        return Vulnerability.objects.filter(target_id=target_id).count()
