import { readFile } from 'node:fs/promises';
import { join } from 'node:path';
import { addAgentPrinciples, addElectronPrinciples } from './platform-principles.js';
/**
 * Auto-detect principles from project knowledge and codebase conventions.
 */
export function deriveAutoDetectedPrinciples(knowledge) {
    /* v8 ignore next 3 -- defensive: caller guarantees non-null knowledge */
    if (!knowledge) {
        return [];
    }
    const principles = [];
    let idx = 0;
    const nextId = () => `auto-${++idx}`;
    // Architecture principle
    principles.push({
        id: nextId(),
        category: 'architecture',
        principle: `Follow ${knowledge.architecture.primary} architecture pattern`,
        rationale: `The project uses ${knowledge.architecture.primary} as its primary architectural pattern. All new code should respect this pattern.`,
        enforceLevel: 'strict',
        autoEnforceable: false,
        source: 'auto-detected',
        immutable: false,
    });
    // Layer boundaries
    if (knowledge.architecture.layers.length > 0) {
        for (const layer of knowledge.architecture.layers) {
            if (layer.neverDependsOn.length > 0) {
                principles.push({
                    id: nextId(),
                    category: 'architecture',
                    principle: `${layer.name} layer must never depend on ${layer.neverDependsOn.join(', ')}`,
                    rationale: `Layer dependency rule: ${layer.responsibility}`,
                    enforceLevel: 'strict',
                    autoEnforceable: true,
                    source: 'auto-detected',
                    immutable: false,
                });
            }
        }
    }
    // Tech stack principle
    if (knowledge.language) {
        const frameworkPart = knowledge.framework ? ` with ${knowledge.framework}` : '';
        principles.push({
            id: nextId(),
            category: 'tech-stack',
            principle: `Use ${knowledge.language}${frameworkPart} for all new code`,
            rationale: `The project is built with ${knowledge.language}${frameworkPart}. Consistency is critical for maintainability.`,
            enforceLevel: 'strict',
            autoEnforceable: true,
            source: 'auto-detected',
            immutable: false,
        });
    }
    // Package manager principle
    if (knowledge.packageManager) {
        principles.push({
            id: nextId(),
            category: 'conventions',
            principle: `Use ${knowledge.packageManager} as the package manager`,
            rationale: `Project lockfile indicates ${knowledge.packageManager}. Mixing package managers causes conflicts.`,
            enforceLevel: 'strict',
            autoEnforceable: true,
            source: 'auto-detected',
            immutable: false,
        });
    }
    // Database principle
    if (knowledge.database !== 'unknown') {
        principles.push({
            id: nextId(),
            category: 'tech-stack',
            principle: `Use ${knowledge.database} as the database engine`,
            rationale: `The project uses ${knowledge.database}. Data layer changes should target this engine.`,
            enforceLevel: 'strict',
            autoEnforceable: false,
            source: 'auto-detected',
            immutable: false,
        });
    }
    // Linting principles
    const configuredLinters = knowledge.linting.detectedLinters.filter((l) => l.status === 'configured');
    if (configuredLinters.length > 0) {
        principles.push({
            id: nextId(),
            category: 'quality',
            principle: `All code must pass linting (${configuredLinters.map((l) => l.tool).join(', ')})`,
            rationale: 'Linting enforcement ensures code consistency and catches common issues early.',
            enforceLevel: 'strict',
            autoEnforceable: true,
            source: 'auto-detected',
            immutable: false,
        });
    }
    // Quality defaults
    principles.push({
        id: nextId(),
        category: 'quality',
        principle: 'Every spec must have acceptance criteria before implementation',
        rationale: 'SDD methodology requires clear acceptance criteria to validate implementation.',
        enforceLevel: 'strict',
        autoEnforceable: true,
        source: 'auto-detected',
        immutable: true,
    });
    principles.push({
        id: nextId(),
        category: 'security',
        principle: 'Never commit secrets or credentials to version control',
        rationale: 'Secrets in code are a critical security vulnerability.',
        enforceLevel: 'strict',
        autoEnforceable: true,
        source: 'auto-detected',
        immutable: true,
    });
    addAgentPrinciples(knowledge, principles, nextId);
    addElectronPrinciples(knowledge, principles, nextId);
    return principles;
}
/**
 * Try to extract principles from CLAUDE.md or similar rule files.
 */
export async function extractPrinciplesFromClaudeMd(projectPath) {
    const principles = [];
    for (const file of ['CLAUDE.md', '.cursorrules', '.windsurfrules']) {
        try {
            const content = await readFile(join(projectPath, file), 'utf-8');
            const lines = content.split('\n');
            let idx = 0;
            for (const line of lines) {
                const trimmed = line.trim();
                // Extract bullet points that look like rules
                const ruleMatch = /^[-*]\s+(.{10,})$/.exec(trimmed);
                if (ruleMatch?.[1]) {
                    const ruleText = ruleMatch[1];
                    // Classify the principle
                    const category = classifyPrinciple(ruleText);
                    principles.push({
                        id: `claude-md-${++idx}`,
                        category,
                        principle: ruleText,
                        rationale: `Extracted from ${file}`,
                        enforceLevel: 'recommended',
                        autoEnforceable: false,
                        source: 'claude-md',
                        immutable: false,
                    });
                }
            }
        }
        catch {
            // File doesn't exist
        }
    }
    return principles;
}
export function classifyPrinciple(text) {
    const lower = text.toLowerCase();
    if (lower.includes('security') ||
        lower.includes('auth') ||
        lower.includes('secret') ||
        lower.includes('encrypt')) {
        return 'security';
    }
    if (lower.includes('architect') ||
        lower.includes('layer') ||
        lower.includes('pattern') ||
        lower.includes('module')) {
        return 'architecture';
    }
    if (lower.includes('test') ||
        lower.includes('quality') ||
        lower.includes('lint') ||
        lower.includes('format')) {
        return 'quality';
    }
    if (lower.includes('name') ||
        lower.includes('convention') ||
        lower.includes('style') ||
        lower.includes('case')) {
        return 'conventions';
    }
    if (lower.includes('stack') ||
        lower.includes('framework') ||
        lower.includes('language') ||
        lower.includes('database')) {
        return 'tech-stack';
    }
    return 'workflow';
}
export function detectConflicts(existing, incoming) {
    const conflicts = [];
    for (const existingP of existing) {
        const match = incoming.find((p) => p.id === existingP.id && p.enforceLevel !== existingP.enforceLevel);
        if (match) {
            conflicts.push(`Principle "${existingP.id}": enforceLevel changed from "${existingP.enforceLevel}" to "${match.enforceLevel}"`);
        }
    }
    return conflicts;
}
//# sourceMappingURL=principle-detector.js.map