import * as fs from 'fs';
import * as path from 'path';
import { resolveNexusStateDir } from './runtime-registry.js';
import { getSharedNgramIndex } from './ngram-index.js';
const BUILTIN_PATTERNS = [
    {
        patternId: 'pattern_orchestrator_repo_focus',
        name: 'Repo-Focused Orchestration',
        category: 'orchestration',
        summary: 'Bias execution toward code, planner state, and verification when the task clearly targets local implementation.',
        instructions: 'Use repo discovery, planner selection, and verification-first workflows when the prompt is implementation heavy and attached corpora are absent or low-signal.',
        tags: ['repo', 'implementation', 'planner', 'verification'],
        stages: ['bootstrap', 'planning', 'mutation', 'verification'],
        suggestedSkills: ['repo-architecture-scout', 'codex-real-workflow'],
        suggestedWorkflows: ['backend-execution-loop'],
        suggestedHooks: ['run-created-brief'],
        suggestedAutomations: ['verified-followup-automation'],
        suggestedCrews: ['crew_implementation'],
        suggestedSpecialists: [],
        confidence: 0.82,
        successCount: 12,
        failureCount: 1,
    },
    {
        patternId: 'pattern_rag_guided_research',
        name: 'Session RAG Guided Research',
        category: 'rag',
        summary: 'Use attached session collections to ground planning and summarization without promoting raw corpus content into memory.',
        instructions: 'Retrieve only top-ranked chunks from attached collections, summarize their relevance, and keep raw material session-scoped unless distilled findings are validated.',
        tags: ['rag', 'research', 'session', 'retrieval'],
        stages: ['bootstrap', 'planning'],
        suggestedSkills: ['browser-to-mission'],
        suggestedWorkflows: ['research-and-implement'],
        suggestedHooks: ['run-created-brief'],
        suggestedAutomations: [],
        suggestedCrews: ['crew_research'],
        suggestedSpecialists: [],
        confidence: 0.79,
        successCount: 8,
        failureCount: 1,
    },
    {
        patternId: 'pattern_runtime_failure_expansion',
        name: 'Repeated Failure Expansion',
        category: 'workflow',
        summary: 'Escalate swarm breadth and continuation planning when prior runtime traces show repeated failures or blocked verification.',
        instructions: 'Use prior runtime traces to widen the worker set, attach postmortem evidence, and prefer continuation-capable orchestration modes.',
        tags: ['runtime', 'failures', 'continuation', 'swarm'],
        stages: ['planning', 'continuation'],
        suggestedSkills: ['mission-postmortem'],
        suggestedWorkflows: ['research-and-implement'],
        suggestedHooks: ['retry-narrow-scope'],
        suggestedAutomations: ['failure-recovery-automation'],
        suggestedCrews: ['crew_implementation'],
        suggestedSpecialists: [],
        confidence: 0.76,
        successCount: 6,
        failureCount: 2,
    },
    {
        patternId: 'pattern_governed_release',
        name: 'Governed Release Pass',
        category: 'workflow',
        summary: 'Combine release preparation with governance and delivery checks when prompts mention release, ship, or publish work.',
        instructions: 'Run planner selection, release workflows, automation review, and governance gates before packaging or tagging.',
        tags: ['release', 'governance', 'automation'],
        stages: ['planning', 'verification'],
        suggestedSkills: ['codex-real-workflow'],
        suggestedWorkflows: ['release-pipeline'],
        suggestedHooks: ['before-verify-approval'],
        suggestedAutomations: ['verified-followup-automation'],
        suggestedCrews: ['crew_implementation'],
        suggestedSpecialists: [],
        confidence: 0.8,
        successCount: 7,
        failureCount: 0,
    },
    {
        patternId: 'pattern_low_tier_preflight',
        name: 'Low-Tier Preflight Filter',
        category: 'retrieval',
        summary: 'Reserve lower-tier models for filtering, ranking, and summarization while keeping mutation authority on the higher tier.',
        instructions: 'Use low-tier stages for candidate discovery, query rewriting, and compression suggestions. Escalate to the high tier for final planning and mutation.',
        tags: ['model-tier', 'retrieval', 'compression'],
        stages: ['bootstrap', 'planning'],
        suggestedSkills: ['systematic-planning'],
        suggestedWorkflows: [],
        suggestedHooks: [],
        suggestedAutomations: [],
        suggestedCrews: [],
        suggestedSpecialists: [],
        confidence: 0.74,
        successCount: 4,
        failureCount: 0,
    },
    {
        patternId: 'pattern_pack_auth_signup_flow',
        name: 'Auth and Signup Flow Pack',
        category: 'workflow',
        summary: 'Ground common auth, signup, onboarding, and session flows in reusable security-aware defaults without generating stale boilerplate.',
        instructions: 'Use this pack when a task mentions auth, login, signup, registration, onboarding, sessions, passwords, magic links, OAuth, or account creation. Start from the lifecycle and acceptance checks, inspect the target framework, then generate only framework-appropriate code with tests and security review. Never paste secrets, never invent provider config, and never bypass existing auth libraries.',
        tags: ['pattern-pack', 'auth', 'signup', 'registration', 'login', 'onboarding', 'security', 'session'],
        stages: ['bootstrap', 'planning', 'mutation', 'verification'],
        suggestedSkills: ['broken-authentication', 'backend-dev-guidelines', 'frontend-dev-guidelines', 'security-auditor'],
        suggestedWorkflows: ['backend-execution-loop', 'frontend-execution-loop'],
        suggestedHooks: ['before-verify-approval'],
        suggestedAutomations: [],
        suggestedCrews: ['crew_implementation'],
        suggestedSpecialists: [
            'specialist_engineering-engineering-backend-architect',
            'specialist_engineering-engineering-frontend-developer',
            'specialist_engineering-engineering-security-engineer',
        ],
        confidence: 0.81,
        successCount: 0,
        failureCount: 0,
        patternPack: {
            kind: 'flow-kit',
            flows: [
                'email/password signup',
                'login/logout',
                'session refresh',
                'password reset',
                'email verification',
                'OAuth handoff',
                'first-run onboarding',
            ],
            starterFiles: [
                { path: 'auth/provider', purpose: 'Wrap the project auth provider or framework-native session adapter.' },
                { path: 'auth/routes', purpose: 'Handle signup, login, logout, callback, and reset endpoints.' },
                { path: 'auth/ui', purpose: 'Expose signup, login, reset, and verification states.' },
                { path: 'auth/tests', purpose: 'Cover happy path, invalid credentials, session expiry, and access-control regressions.' },
            ],
            memorySeeds: [
                'Auth work must reuse project-native libraries and existing session boundaries before adding new dependencies.',
                'Signup flows need explicit abuse, rate-limit, email verification, and password-reset checks.',
                'Never store provider secrets, reset tokens, or session material in Nexus memory.',
            ],
            lifecycle: [
                'Detect framework and existing auth surface.',
                'Select provider pattern and security constraints.',
                'Patch smallest route, UI, and persistence surface.',
                'Verify with unit, integration, and access-control checks.',
                'Store only sanitized implementation decisions as memory.',
            ],
            acceptanceChecks: [
                'Unauthenticated users cannot access protected routes.',
                'Signup and login errors are explicit without leaking account existence.',
                'Sessions expire or refresh according to project policy.',
                'Password reset and verification tokens are one-time and scoped.',
                'Tests cover success, failure, and privilege-boundary cases.',
            ],
            antiPatterns: [
                'Rolling custom crypto.',
                'Saving secrets or tokens into memory.',
                'Adding auth dependencies before checking existing stack.',
                'Generating UI-only signup without backend/session proof.',
            ],
        },
    },
];
export class PatternRegistry {
    statePath;
    cards;
    ngramIndex = null;
    constructor(stateRoot = resolveNexusStateDir()) {
        this.statePath = path.join(stateRoot, 'pattern-registry.json');
        try {
            this.ngramIndex = getSharedNgramIndex();
        }
        catch {
            this.ngramIndex = null;
        }
        this.cards = this.loadCards();
        this.indexAllCards();
    }
    indexAllCards() {
        try {
            for (const card of this.cards) {
                this.ngramIndex?.addDocument(card.patternId, card.name + ' ' + card.summary + ' ' + card.instructions);
            }
        }
        catch {
            // n-gram indexing is best-effort
        }
    }
    list() {
        return [...this.cards].sort((left, right) => {
            const leftScore = left.successCount - left.failureCount;
            const rightScore = right.successCount - right.failureCount;
            return rightScore - leftScore || left.name.localeCompare(right.name);
        });
    }
    search(query, limit = 5) {
        const keywords = extractKeywords(query);
        // N-gram pre-filter: narrow to likely candidates before keyword scoring
        let pool = this.cards;
        try {
            const ngramHits = this.ngramIndex?.search(query, 10);
            if (ngramHits && ngramHits.length > 0) {
                const hitIds = new Set(ngramHits.map((h) => h.docId));
                const filtered = this.cards.filter((c) => hitIds.has(c.patternId));
                if (filtered.length > 0) {
                    pool = filtered;
                }
            }
        }
        catch {
            // n-gram search failed; fall back to full scan
        }
        const results = pool
            .map((card) => {
            const successBias = Math.max(0, card.successCount - card.failureCount);
            const score = scoreText(`${card.name}\n${card.summary}\n${card.instructions}\n${card.tags.join(' ')}`, keywords)
                + Math.round(card.confidence * 10)
                + successBias;
            return { ...card, score };
        })
            .filter((card) => card.score >= 0)
            .sort((left, right) => right.score - left.score || left.name.localeCompare(right.name))
            .slice(0, Math.max(1, Math.min(12, limit)));
        if (results.length === 0) {
            return this.cards
                .sort((a, b) => (b.confidence * 10 + b.successCount) - (a.confidence * 10 + a.successCount))
                .slice(0, limit)
                .map((card) => ({ ...card, score: Math.round(card.confidence * 10) }));
        }
        return results;
    }
    recordOutcome(patternId, success) {
        const card = this.cards.find((entry) => entry.patternId === patternId);
        if (!card)
            return;
        if (success) {
            card.successCount += 1;
        }
        else {
            card.failureCount += 1;
        }
        card.lastUsedAt = Date.now();
        this.persist();
    }
    loadCards() {
        if (!fs.existsSync(this.statePath)) {
            this.persistCards(BUILTIN_PATTERNS);
            return BUILTIN_PATTERNS.map((card) => ({ ...card }));
        }
        try {
            const parsed = JSON.parse(fs.readFileSync(this.statePath, 'utf8'));
            const byId = new Map(parsed.map((card) => [card.patternId, card]));
            for (const builtin of BUILTIN_PATTERNS) {
                if (!byId.has(builtin.patternId)) {
                    byId.set(builtin.patternId, { ...builtin });
                }
            }
            const cards = [...byId.values()];
            this.persistCards(cards);
            return cards;
        }
        catch {
            this.persistCards(BUILTIN_PATTERNS);
            return BUILTIN_PATTERNS.map((card) => ({ ...card }));
        }
    }
    persist() {
        this.persistCards(this.cards);
    }
    persistCards(cards) {
        fs.writeFileSync(this.statePath, JSON.stringify(cards, null, 2), 'utf8');
    }
}
function extractKeywords(value) {
    return String(value || '')
        .toLowerCase()
        .split(/[^a-z0-9]+/)
        .filter((token) => token.length >= 3);
}
function scoreText(value, keywords) {
    const lower = String(value || '').toLowerCase();
    return keywords.reduce((sum, keyword) => sum + (lower.includes(keyword) ? 3 : 0), 0);
}
