// engine/detectors/platform-specialty-detector.ts
// SPEC-015a + SPEC-015b: Detection functions for specialty platforms
// Bots, Smart Contracts, ML/AI, Data Pipelines, IaC, IoT/Embedded
import { fileExists, hasAnyFile, collectDependencies } from '../detection-utils.js';
// === Bot detection ===
const BOT_DEPS = {
    discord: ['discord.js', 'discordjs'],
    telegram: ['telegraf', 'grammy', 'node-telegram-bot-api'],
    slack: ['@slack/bolt', '@slack/web-api'],
    whatsapp: ['whatsapp-web.js', 'baileys', '@whiskeysockets/baileys'],
};
function detectBotFromDeps(deps) {
    for (const [platform, signatures] of Object.entries(BOT_DEPS)) {
        if (signatures.some((d) => deps.has(d))) {
            return platform;
        }
    }
    return null;
}
// === Smart Contract detection ===
async function detectSmartContractFramework(projectPath, deps) {
    if (deps.has('hardhat') ||
        (await fileExists(projectPath, 'hardhat.config.ts')) ||
        (await fileExists(projectPath, 'hardhat.config.js'))) {
        return 'hardhat';
    }
    if (await fileExists(projectPath, 'foundry.toml')) {
        return 'foundry';
    }
    if (deps.has('@coral-xyz/anchor') || (await fileExists(projectPath, 'Anchor.toml'))) {
        return 'anchor';
    }
    if (await fileExists(projectPath, 'Move.toml')) {
        return 'move';
    }
    return null;
}
// SPEC-015b: Detect Vyper contracts (*.vy files)
async function detectVyper(projectPath) {
    return hasAnyFile(projectPath, ['*.vy', '**/*.vy']);
}
// === ML/AI detection ===
const ML_DEPS = {
    pytorch: ['torch', 'pytorch'],
    tensorflow: ['tensorflow', 'tf-nightly', 'keras'],
    sklearn: ['scikit-learn', 'sklearn'],
    langchain: ['langchain', 'langchain-core', 'langchain-openai'],
    huggingface: ['transformers', 'datasets', 'huggingface-hub'],
};
// SPEC-015b: Additional ML deps for extended detection
const ML_EXTENDED_DEPS = {
    jax: 'pytorch', // JAX mapped to pytorch category for now (same tensor ecosystem)
    flax: 'pytorch',
    'llama-index': 'langchain',
    llamaindex: 'langchain',
    'sentence-transformers': 'huggingface',
};
function detectMLFrameworks(deps) {
    const found = new Set();
    for (const [framework, signatures] of Object.entries(ML_DEPS)) {
        if (signatures.some((d) => deps.has(d))) {
            found.add(framework);
        }
    }
    // SPEC-015b: extended ML deps
    for (const [dep, framework] of Object.entries(ML_EXTENDED_DEPS)) {
        if (deps.has(dep) && framework !== undefined) {
            found.add(framework);
        }
    }
    return Array.from(found);
}
// SPEC-015b: Detect ML task type from dependency signals
function detectMLTaskType(deps) {
    if (deps.has('transformers') || deps.has('llama-index') || deps.has('llamaindex')) {
        return 'text-generation';
    }
    if (deps.has('sentence-transformers') || deps.has('faiss-cpu') || deps.has('chromadb')) {
        return 'embeddings';
    }
    if (deps.has('torchvision') || deps.has('timm') || deps.has('Pillow')) {
        return 'vision';
    }
    if (deps.has('scikit-learn') || deps.has('sklearn')) {
        // sklearn can do both classification and regression — default to classification
        return 'classification';
    }
    return null;
}
// === Data pipeline detection ===
// SPEC-015b: Extended data pipeline detection (Prefect, Dagster)
async function detectDataPipeline(projectPath, deps) {
    if (deps.has('apache-airflow') || (await hasAnyFile(projectPath, ['dags/']))) {
        return 'airflow';
    }
    if (deps.has('dbt-core') || (await fileExists(projectPath, 'dbt_project.yml'))) {
        return 'dbt';
    }
    if (deps.has('prefect')) {
        return 'prefect';
    }
    if (deps.has('dagster') || deps.has('dagster-webserver')) {
        return 'dagster';
    }
    if (deps.has('pyspark') || (await fileExists(projectPath, 'spark-defaults.conf'))) {
        return 'spark';
    }
    return null;
}
// SPEC-015b: Infer pipeline type from detected tool
function inferPipelineType(tool) {
    if (tool === null) {
        return null;
    }
    if (tool === 'spark') {
        return 'streaming'; // Spark commonly used for streaming
    }
    return 'batch'; // Airflow, dbt, Prefect, Dagster are primarily batch
}
// === IaC detection ===
async function detectIaCTools(projectPath, deps) {
    const found = [];
    const hasTf = await hasAnyFile(projectPath, ['*.tf', '**/*.tf']);
    if (hasTf) {
        found.push('terraform');
    }
    if (await fileExists(projectPath, 'Pulumi.yaml')) {
        found.push('pulumi');
    }
    if (deps.has('aws-cdk-lib') ||
        deps.has('aws-cdk') ||
        (await fileExists(projectPath, 'cdk.json'))) {
        found.push('cdk');
    }
    const hasAnsible = await hasAnyFile(projectPath, ['ansible.cfg', 'playbook.yml', 'site.yml']);
    if (hasAnsible) {
        found.push('ansible');
    }
    // SPEC-015b: CloudFormation detection
    const hasCfn = await fileExists(projectPath, 'template.yaml');
    if (hasCfn) {
        found.push('cloudformation');
    }
    return found;
}
// SPEC-015b: Detect IaC state backend from files
async function detectIaCStateBackend(projectPath, deps) {
    // Check for Terraform cloud backend or S3 backend in .terraform.lock.hcl
    const hasTfLock = await fileExists(projectPath, '.terraform.lock.hcl');
    if (hasTfLock) {
        // Default state backend when lock file is present and no cloud-specific deps
        if (deps.has('@aws-sdk/client-s3') || deps.has('aws-sdk')) {
            return 's3';
        }
        return 'local';
    }
    if (deps.has('@google-cloud/storage')) {
        return 'gcs';
    }
    return null;
}
// === IoT/Embedded detection ===
async function detectIoTPlatform(projectPath) {
    const hasIno = await hasAnyFile(projectPath, ['*.ino', '**/*.ino']);
    if (hasIno) {
        return 'arduino';
    }
    if (await fileExists(projectPath, 'platformio.ini')) {
        return 'platformio';
    }
    if (await fileExists(projectPath, 'prj.conf')) {
        return 'zephyr';
    }
    return null;
}
// SPEC-015b: Detect specific IoT microcontroller from platformio.ini or deps
async function detectIoTMicrocontroller(projectPath, deps) {
    // Raspberry Pi detection via Python GPIO libs
    if (deps.has('RPi.GPIO') || deps.has('gpiozero') || deps.has('rpi-gpio')) {
        return 'raspberry-pi';
    }
    // PlatformIO with ESP32 boards detected via platformio.ini existence
    // (we can't parse the INI easily, but if platformio.ini exists, common boards are ESP)
    const hasPlatformIO = await fileExists(projectPath, 'platformio.ini');
    if (hasPlatformIO) {
        // SPEC-015b: Check if esp32 is mentioned in any config file via dep signal
        if (deps.has('esp-idf') || deps.has('espidf')) {
            return 'esp32';
        }
        // Default to esp32 as most common PlatformIO target
        return 'esp32';
    }
    const hasIno = await hasAnyFile(projectPath, ['*.ino', '**/*.ino']);
    if (hasIno) {
        return 'arduino-uno';
    }
    return null;
}
// SPEC-015b: Detect IoT communication protocol from deps
function detectIoTProtocol(deps) {
    if (deps.has('mqtt') || deps.has('paho-mqtt') || deps.has('async-mqtt')) {
        return 'mqtt';
    }
    if (deps.has('bleak') || deps.has('bluepy') || deps.has('noble')) {
        return 'ble';
    }
    if (deps.has('zigpy') || deps.has('zigbee2mqtt')) {
        return 'zigbee';
    }
    if (deps.has('pyloralib') || deps.has('lora')) {
        return 'lora';
    }
    return 'http'; // default fallback for IoT projects without specific protocol
}
// SPEC-015b: Detect OTA update capability
async function detectIoTOTA(projectPath, deps) {
    if (deps.has('esp-idf') || deps.has('espressif__esp-mqtt')) {
        return true; // ESP-IDF supports OTA natively
    }
    const hasPlatformIO = await fileExists(projectPath, 'platformio.ini');
    return hasPlatformIO; // PlatformIO projects commonly support OTA
}
// === Main export ===
/**
 * Detect all specialty platforms for a project.
 * Collects dependencies once and runs all detections in parallel.
 */
export async function detectPlatformSpecialty(projectPath) {
    const deps = await collectDependencies(projectPath);
    const [smartContractFramework, dataPipeline, iacTools, iotPlatform, iacStateBackend, iotMicrocontroller, vyperDetected, iotHasOTA,] = await Promise.all([
        detectSmartContractFramework(projectPath, deps),
        detectDataPipeline(projectPath, deps),
        detectIaCTools(projectPath, deps),
        detectIoTPlatform(projectPath),
        detectIaCStateBackend(projectPath, deps),
        detectIoTMicrocontroller(projectPath, deps),
        detectVyper(projectPath),
        detectIoTOTA(projectPath, deps),
    ]);
    const botPlatform = detectBotFromDeps(deps);
    const mlFrameworks = detectMLFrameworks(deps);
    const mlTaskType = detectMLTaskType(deps);
    const dataPipelineType = inferPipelineType(dataPipeline);
    const iotProtocol = iotPlatform !== null ? detectIoTProtocol(deps) : null;
    return {
        botPlatform,
        smartContractFramework,
        mlFrameworks,
        dataPipeline,
        iacTools,
        iotPlatform,
        // SPEC-015b advanced fields
        mlTaskType,
        dataPipelineType,
        iacStateBackend,
        iotMicrocontroller,
        iotProtocol,
        iotHasOTA,
        vyperDetected,
    };
}
//# sourceMappingURL=platform-specialty-detector.js.map