"""
导出 URL 任务

支持两种模式：
1. 传统模式（向后兼容）：使用 target_id 从数据库导出
2. Provider 模式：使用 TargetProvider 从任意数据源导出

用于指纹识别前导出目标下的 URL 到文件
"""

import logging
from typing import Optional
from pathlib import Path

from prefect import task

from apps.scan.services.target_export_service import (
    export_urls_with_fallback,
    DataSource,
)
from apps.scan.providers import TargetProvider, DatabaseTargetProvider

logger = logging.getLogger(__name__)


@task(name="export_urls_for_fingerprint")
def export_urls_for_fingerprint_task(
    target_id: Optional[int] = None,
    output_file: str = "",
    source: str = 'website',  # 保留参数，兼容旧调用（实际值由回退链决定）
    provider: Optional[TargetProvider] = None,
    batch_size: int = 1000
) -> dict:
    """
    导出目标下的 URL 到文件（用于指纹识别）
    
    支持两种模式：
    1. 传统模式（向后兼容）：传入 target_id，从数据库导出
    2. Provider 模式：传入 provider，从任意数据源导出
    
    数据源优先级（回退链，仅传统模式）：
    1. WebSite 表 - 站点级别 URL
    2. 默认生成 - 根据 Target 类型生成 http(s)://target_name
    
    Args:
        target_id: 目标 ID（传统模式，向后兼容）
        output_file: 输出文件路径
        source: 数据源类型（保留参数，兼容旧调用，实际值由回退链决定）
        provider: TargetProvider 实例（新模式）
        batch_size: 批量读取大小
    
    Returns:
        dict: {'output_file': str, 'total_count': int, 'source': str}
    """
    # 参数验证：至少提供一个
    if target_id is None and provider is None:
        raise ValueError("必须提供 target_id 或 provider 参数之一")
    
    # Provider 模式：使用 TargetProvider 导出
    if provider is not None:
        logger.info("使用 Provider 模式 - Provider: %s", type(provider).__name__)
        return _export_with_provider(output_file, provider)
    
    # 传统模式：使用 export_urls_with_fallback
    logger.info("使用传统模式 - Target ID: %d", target_id)
    result = export_urls_with_fallback(
        target_id=target_id,
        output_file=output_file,
        sources=[DataSource.WEBSITE, DataSource.DEFAULT],
        batch_size=batch_size,
    )
    
    logger.info(
        "指纹识别 URL 导出完成 - source=%s, count=%d",
        result['source'], result['total_count']
    )
    
    # 返回实际使用的数据源（不再固定为 "website"）
    return {
        'output_file': result['output_file'],
        'total_count': result['total_count'],
        'source': result['source'],
    }


def _export_with_provider(output_file: str, provider: TargetProvider) -> dict:
    """使用 Provider 导出 URL"""
    output_path = Path(output_file)
    output_path.parent.mkdir(parents=True, exist_ok=True)
    
    total_count = 0
    blacklist_filter = provider.get_blacklist_filter()
    
    with open(output_path, 'w', encoding='utf-8', buffering=8192) as f:
        for url in provider.iter_urls():
            # 应用黑名单过滤（如果有）
            if blacklist_filter and not blacklist_filter.is_allowed(url):
                continue
            
            f.write(f"{url}\n")
            total_count += 1
            
            if total_count % 1000 == 0:
                logger.info("已导出 %d 个 URL...", total_count)
    
    logger.info("✓ URL 导出完成 - 总数: %d, 文件: %s", total_count, str(output_path))
    
    return {
        'output_file': str(output_path),
        'total_count': total_count,
        'source': 'provider',
    }
