// engine/detectors/idp-detector.ts — Internal Developer Platform (IDP) detection (SPEC-026b)
// Detects Backstage, Port.io, Cortex, and OpsLevel IDP configurations.
import { readFile } from 'node:fs/promises';
import { join } from 'node:path';
import { glob } from 'glob';
// === Detection signals ===
const IDP_SIGNALS = [
    {
        tool: 'backstage',
        configFiles: ['catalog-info.yaml', 'catalog-info.yml'],
        nameField: 'metadata.name',
        ownerField: 'spec.owner',
    },
    {
        tool: 'port-io',
        configFiles: [],
        globPatterns: ['.port/port-app-config.yml', '.port/port-app-config.yaml'],
        nameField: 'identifier',
        ownerField: 'team',
    },
    {
        tool: 'cortex',
        configFiles: ['cortex.yaml', 'cortex.yml'],
        nameField: 'info.x-cortex-tag',
        ownerField: 'info.x-cortex-team',
    },
    {
        tool: 'opslevel',
        configFiles: ['.opslevel.yml', '.opslevel.yaml'],
        nameField: 'name',
        ownerField: 'owner',
    },
];
// === Public API ===
/**
 * Detects IDP configuration in a project.
 * Returns the first IDP found (Backstage > Port > Cortex > OpsLevel).
 */
export async function detectIdp(projectPath) {
    for (const signal of IDP_SIGNALS) {
        const found = await findIdpFile(projectPath, signal);
        if (found !== null) {
            const { configFile, content } = found;
            /* v8 ignore start */
            const componentName = extractYamlField(content, signal.nameField ?? 'metadata.name');
            const owner = extractYamlField(content, signal.ownerField ?? 'spec.owner');
            /* v8 ignore stop */
            return {
                tool: signal.tool,
                componentName,
                owner,
                configFile,
            };
        }
    }
    return { tool: null, componentName: null, owner: null, configFile: null };
}
// === Internal helpers ===
async function findIdpFile(projectPath, signal) {
    // Check explicit config files
    for (const f of signal.configFiles) {
        try {
            const content = await readFile(join(projectPath, f), 'utf-8');
            return { configFile: f, content };
        }
        catch {
            // not found, continue
        }
    }
    // Check glob patterns
    if (signal.globPatterns) {
        for (const pattern of signal.globPatterns) {
            try {
                const matches = await glob(pattern, { cwd: projectPath, nodir: true });
                if (matches.length > 0) {
                    const first = matches[0];
                    /* v8 ignore start */
                    if (first !== undefined) {
                        try {
                            const content = await readFile(join(projectPath, first), 'utf-8');
                            return { configFile: first, content };
                        }
                        catch {
                            // ignore
                        }
                    }
                    /* v8 ignore stop */
                }
            }
            catch {
                // ignore glob errors
            }
        }
    }
    return null;
}
/**
 * Extracts a value from YAML-like content using dot-notation path.
 * Simple regex-based extraction — does not require a YAML parser.
 */
function extractYamlField(content, fieldPath) {
    /* v8 ignore start */
    const lastKey = fieldPath.split('.').at(-1);
    if (!lastKey) {
        return null;
    }
    /* v8 ignore stop */
    // Look for "key: value" pattern in the content
    const regex = new RegExp(`^\\s*${escapeRegex(lastKey)}:\\s*(.+)$`, 'm');
    const match = regex.exec(content);
    if (!match) {
        return null;
    }
    /* v8 ignore start */
    const value = match[1]?.trim();
    if (!value || value === 'null' || value === '~') {
        return null;
    }
    /* v8 ignore stop */
    // Remove surrounding quotes if present
    return value.replace(/^['"]|['"]$/g, '');
}
function escapeRegex(str) {
    return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
}
//# sourceMappingURL=idp-detector.js.map