"""
扫描工具命令模板（简化版，不使用 Jinja2）

使用 Python 原生字符串格式化，零依赖。
"""

from django.conf import settings

# ==================== 路径配置 ====================
SCAN_TOOLS_BASE_PATH = getattr(settings, 'SCAN_TOOLS_BASE_PATH', '/usr/local/bin')

# ==================== 子域名发现 ====================

SUBDOMAIN_DISCOVERY_COMMANDS = {
    'subfinder': {
        # 默认使用所有数据源（更全面，略慢），并始终开启递归
        # -all       使用所有数据源
        # -recursive 对支持递归的源启用递归枚举（默认开启）
        'base': "subfinder -d {domain} -all -recursive -o '{output_file}' -silent",
        'optional': {
            'threads': '-t {threads}',              # 控制并发 goroutine 数
        }
    },
    
    'amass_passive': {
        # 先执行被动枚举，将结果写入 amass 内部数据库，然后从数据库中导出纯域名（names）到 output_file
        # -silent 禁用进度条和其他输出
        'base': "amass enum -passive -silent -d {domain} && amass subs -names -d {domain} > '{output_file}'"
    },
    
    'amass_active': {
        # 先执行主动枚举 + 爆破，将结果写入 amass 内部数据库，然后从数据库中导出纯域名（names）到 output_file
        # -silent 禁用进度条和其他输出
        'base': "amass enum -active -silent -d {domain} -brute && amass subs -names -d {domain} > '{output_file}'"
    },
    
    'sublist3r': {
        'base': "python3 '/usr/local/share/Sublist3r/sublist3r.py' -d {domain} -o '{output_file}'",
        'optional': {
            'threads': '-t {threads}'
        }
    },
    
    'assetfinder': {
        'base': "assetfinder --subs-only {domain} > '{output_file}'",
    },
    
    # === 主动字典爆破 ===
    'subdomain_bruteforce': {
        # 使用字典对目标域名进行 DNS 爆破
        # -d 目标域名，-w 字典文件，-o 输出文件
        'base': "puredns bruteforce '{wordlist}' {domain} -r /app/backend/resources/resolvers.txt --write '{output_file}' --quiet",
        'optional': {},
    },
    
    # === DNS 存活验证（最终统一验证）===
    'subdomain_resolve': {
        # 验证子域名是否能解析（存活验证）
        # 输入文件为候选子域列表，输出为存活子域列表
        'base': "puredns resolve '{input_file}' -r /app/backend/resources/resolvers.txt --write '{output_file}' --wildcard-tests 50 --wildcard-batch 1000000 --quiet",
        'optional': {},
    },
    
    # === 变异生成 + 存活验证（流式管道，避免 OOM）===
    'subdomain_permutation_resolve': {
        # 流式管道：dnsgen 生成变异域名 | puredns resolve 验证存活
        # 不落盘中间文件，避免内存爆炸；不做通配符过滤
        'base': "cat '{input_file}' | dnsgen - | puredns resolve -r /app/backend/resources/resolvers.txt --write '{output_file}' --wildcard-tests 50 --wildcard-batch 1000000 --quiet",
        'optional': {},
    },
}


# ==================== 端口扫描 ====================

PORT_SCAN_COMMANDS = {
    'naabu_active': {
        'base': "naabu -exclude-cdn -warm-up-time 5 -verify -list '{domains_file}' -json -silent",
        'optional': {
            'threads': '-c {threads}',
            'ports': '-p {ports}',
            'top_ports': '-top-ports {top_ports}',
            'rate': '-rate {rate}'
        }
    },
    
    'naabu_passive': {
        'base': "naabu -list '{domains_file}' -passive -json -silent"
    },
}


# ==================== 站点扫描 ====================

SITE_SCAN_COMMANDS = {
    'httpx': {
        'base': (
            "'{scan_tools_base}/httpx' -l '{url_file}' "
            '-status-code -content-type -content-length '
            '-location -title -server '
            '-tech-detect -cdn -vhost '
            '-include-response '
            '-rstr 2000 '
            '-random-agent -no-color -json -silent'
        ),
        'optional': {
            'threads': '-threads {threads}',
            'rate_limit': '-rate-limit {rate_limit}',
            'request_timeout': '-timeout {request_timeout}',
            'retries': '-retries {retries}'
        }
    },
}


# ==================== 目录扫描 ====================

DIRECTORY_SCAN_COMMANDS = {
    'ffuf': {
        'base': "'{scan_tools_base}/ffuf' -u '{url}FUZZ' -se -ac -sf -json -w '{wordlist}'",  
        'optional': {
            'delay': '-p {delay}',
            'threads': '-t {threads}',
            'request_timeout': '-timeout {request_timeout}',
            'match_codes': '-mc {match_codes}',
            'rate': '-rate {rate}'
        }
    },
}


# ==================== URL 获取 ====================

URL_FETCH_COMMANDS = {
    'waymore': {
        'base': "waymore -i {domain_name} -mode U -oU '{output_file}'",
        'input_type': 'domain_name'
    },
    
    'katana': {
        'base': (
            "katana -list '{sites_file}' -o '{output_file}' "
            '-jc '                   # 开启 JavaScript 爬取 + 自动解析 .js 文件里的所有端点（最重要）
            '-xhr '                  # 额外从 JS 中提取 XHR/Fetch 请求的 API 路径（再多挖 10-20% 隐藏接口）
            '-kf all '               # 在每个目录下自动 fuzz 所有已知敏感文件（.env、.git、backup、config、ds_store 等 5000+ 条）
            '-fs rdn '               # 智能过滤相对重复+噪声路径（分页、?id=1/2/3 这类垃圾全干掉，输出极干净）
            '-H "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36" '  # 固定一个正常 UA（Katana 默认会随机，但固定更低调）
            '-silent '               # 安静模式（终端不输出进度条，只出 URL）
        ),
        'optional': {
            'depth': '-d {depth}',                      # 爬取最大深度（平衡深度与时间，默认 3，推荐 5）
            'threads': '-c {threads}',                  # 全局并发数（极低并发最像真人，推荐 10）
            'rate_limit': '-rl {rate_limit}',           # 全局硬限速：每秒最多 N 个请求（WAF 几乎不报警，推荐 30）
            'random_delay': '-rd {random_delay}',       # 每次请求之间随机延迟 N 秒（再加一层人性化，推荐 1）
            'retry': '-retry {retry}',                  # 失败请求自动重试次数（网络抖动不丢包，推荐 2）
            'request_timeout': '-timeout {request_timeout}'  # 单请求超时秒数（防卡死，推荐 12）
        },
        'input_type': 'sites_file'
    },
    
    'uro': {
        'base': "uro -i '{input_file}' -o '{output_file}'",
        'optional': {
            'whitelist': '-w {whitelist}',      # 只保留指定扩展名的 URL（空格分隔）
            'blacklist': '-b {blacklist}',      # 排除指定扩展名的 URL（空格分隔）
            'filters': '-f {filters}'           # 额外的过滤规则（空格分隔）
        }
    },
    
    'httpx': {
        'base': (
            "'{scan_tools_base}/httpx' -l '{url_file}' "
            '-status-code -content-type -content-length '
            '-location -title -server '
            '-tech-detect -cdn -vhost '
            '-include-response '
            '-rstr 2000 '
            '-random-agent -no-color -json -silent'
        ),
        'optional': {
            'threads': '-threads {threads}',
            'rate_limit': '-rate-limit {rate_limit}',
            'request_timeout': '-timeout {request_timeout}',
            'retries': '-retries {retries}'
        }
    },
}

VULN_SCAN_COMMANDS = {
    'dalfox_xss': {
        'base': (
            'dalfox --silence --no-color --no-spinner '
            '--skip-bav '
            "file '{endpoints_file}' "
            '--waf-evasion '
            '--format json'
        ),
        'optional': {
            'only_poc': '--only-poc {only_poc}',
            'ignore_return': '--ignore-return {ignore_return}',
            'blind_xss_server': '-b {blind_xss_server}',
            'delay': '--delay {delay}',
            'request_timeout': '--timeout {request_timeout}',
            # 是否追加 UA 头，由 user_agent 是否存在决定
            'user_agent': '--user-agent "{user_agent}"',
            'worker': '--worker {worker}',
        },
        'input_type': 'endpoints_file',
    },
    'nuclei': {
        # nuclei 漏洞扫描
        # -j: JSON 输出（每行一条完整 JSON）
        # -silent: 静默模式
        # -l: 输入 URL 列表文件
        # -t: 模板目录路径（支持多个仓库，多次 -t 由 template_args 直接拼接）
        'base': "nuclei -j -silent -l '{endpoints_file}' {template_args}",
        'optional': {
            'concurrency': '-c {concurrency}',           # 并发数（默认 25）
            'rate_limit': '-rl {rate_limit}',            # 每秒请求数限制
            'request_timeout': '-timeout {request_timeout}',  # 请求超时秒数
            'bulk_size': '-bs {bulk_size}',              # 批量处理大小
            'retries': '-retries {retries}',             # 重试次数
            'severity': '-severity {severity}',          # 过滤严重性（info,low,medium,high,critical）
            'tags': '-tags {tags}',                      # 过滤标签
            'exclude_tags': '-etags {exclude_tags}',     # 排除标签
        },
        'input_type': 'endpoints_file',
    },
}


# ==================== 指纹识别 ====================

FINGERPRINT_DETECT_COMMANDS = {
    'xingfinger': {
        # 流式输出模式（不使用 -o，输出到 stdout）
        # -l: URL 列表文件输入
        # -s: 静默模式，只输出命中结果
        # --json: JSON 格式输出（每行一条）
        'base': "xingfinger -l '{urls_file}' -s --json",
        'optional': {
            # 自定义指纹库路径
            'ehole': '--ehole {ehole}',
            'goby': '--goby {goby}',
            'wappalyzer': '--wappalyzer {wappalyzer}',
            'fingers': '--fingers {fingers}',
            'fingerprinthub': '--fingerprint {fingerprinthub}',
            'arl': '--arl {arl}',
        }
    },
}


# ==================== 工具映射 ====================

COMMAND_TEMPLATES = {
    'subdomain_discovery': SUBDOMAIN_DISCOVERY_COMMANDS,
    'port_scan': PORT_SCAN_COMMANDS,
    'site_scan': SITE_SCAN_COMMANDS,
    'fingerprint_detect': FINGERPRINT_DETECT_COMMANDS,
    'directory_scan': DIRECTORY_SCAN_COMMANDS,
    'url_fetch': URL_FETCH_COMMANDS,
    'vuln_scan': VULN_SCAN_COMMANDS,
}

# ==================== 扫描类型配置 ====================

# 执行阶段定义（按顺序执行）
EXECUTION_STAGES = [
    {
        'mode': 'sequential',
        'flows': ['subdomain_discovery', 'port_scan', 'site_scan', 'fingerprint_detect']
    },
    {
        'mode': 'parallel',
        'flows': ['url_fetch', 'directory_scan']
    },
    {
        'mode': 'sequential',
        'flows': ['vuln_scan']
    },
]


def get_supported_scan_types():
    """
    获取支持的扫描类型
    
    Returns:
        list: 支持的扫描类型列表（从 COMMAND_TEMPLATES 的 keys 获取）
    """
    return list(COMMAND_TEMPLATES.keys())


def get_command_template(scan_type: str, tool_name: str) -> dict:
    """
    获取工具的命令模板
    
    Args:
        scan_type: 扫描类型
        tool_name: 工具名称
    
    Returns:
        命令模板字典，如果未找到则返回 None
    """
    templates = COMMAND_TEMPLATES.get(scan_type, {})
    return templates.get(tool_name)
