"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.PatternStore = void 0;
const fs = __importStar(require("fs"));
const path = __importStar(require("path"));
const types_1 = require("../../../types");
const confidence_engine_1 = require("../../../core/confidence-engine");
const pattern_validator_1 = require("../../../core/pattern-validator");
const pattern_search_1 = require("../../../core/pattern-search");
const pattern_ranking_1 = require("../../../core/pattern-ranking");
const pattern_quality_1 = require("../../../core/pattern-quality");
const pattern_lifecycle_1 = require("../../../core/pattern-lifecycle");
const pattern_relationships_1 = require("../../../core/pattern-relationships");
const pattern_classifier_1 = require("../../../core/pattern-classifier");
const crypto_1 = require("crypto");
class PatternStore {
    storePath;
    patterns;
    patternIndex;
    confidenceEngine;
    validator;
    searchEngine;
    rankingEngine;
    qualityEngine;
    lifecycleTracker;
    relationshipEngine;
    validationLog;
    constructor(cellDir) {
        this.storePath = path.join(cellDir, 'cell.json');
        this.patterns = new Map();
        this.patternIndex = new Map();
        this.confidenceEngine = new confidence_engine_1.ConfidenceEngine();
        this.validator = new pattern_validator_1.PatternValidator();
        this.searchEngine = new pattern_search_1.PatternSearch();
        this.rankingEngine = new pattern_ranking_1.RankingEngine();
        this.qualityEngine = new pattern_quality_1.QualityEngine();
        this.lifecycleTracker = new pattern_lifecycle_1.LifecycleTracker();
        this.relationshipEngine = new pattern_relationships_1.RelationshipEngine();
        this.validationLog = [];
        this.ensureDirectory(cellDir);
        this.load();
    }
    addOrUpdatePattern(category, description, from, to, isPositive, conditions = [], scope = 'global', stepUsed, language) {
        const lang = language || 'unknown';
        const validation = this.validator.validate(category, from, to, lang);
        this.validationLog.push(validation);
        if (!validation.valid) {
            const nullPat = {
                patternId: 'invalid', category, description, from, to, conditions,
                confidence: { distribution: 'beta', alpha: 0, beta: 0, mean: 0, ci95: [0, 0] },
                signals: { positive: 0, negative: 0, total: 0, lastSignal: 0 },
                attribution: { primaryCondition: '', conditionConfidence: 0, sourceFiles: [], note: '' },
                scope: 'global', survivedDays: 0,
                meta: { language: lang, subcategory: 'general', complexity: 'low', risk: 'medium', source: 'manual' },
                lifecycle: { firstSeen: 0, lastSeen: 0, version: 0, history: [] },
                quality: { score: 0, reuseRate: 0, successRate: 0, failureRate: 0, acceptanceRate: 0, daysSinceLastSignal: 0, age: 0 },
                relationships: { related: [], conflicting: [], complementary: [], dependencies: [] },
                ranking: { score: 0, rank: 0, factors: { confidence: 0, quality: 0, usage: 0, recency: 0, acceptance: 0 } },
            };
            return nullPat;
        }
        const existingKey = this.findExistingPattern(category, from, to);
        if (existingKey) {
            return this.updatePattern(existingKey, isPositive, stepUsed, lang);
        }
        return this.createPattern(category, description, from, to, isPositive, conditions, scope, stepUsed, lang);
    }
    createPattern(category, description, from, to, isPositive, conditions, scope, stepUsed, language) {
        const patternId = `p_${(0, crypto_1.randomUUID)()}`;
        const positive = isPositive ? 1 : 0;
        const negative = isPositive ? 0 : 1;
        const now = Date.now();
        const source = (0, pattern_classifier_1.inferSource)(stepUsed || 'manual');
        const classification = (0, pattern_classifier_1.classifyPattern)(category, from, to, language || 'unknown', source);
        const meta = {
            language: classification.language,
            subcategory: classification.subcategory,
            complexity: classification.complexity,
            risk: classification.risk,
            source: classification.source,
        };
        const confidence = this.confidenceEngine.computeConfidence(positive, negative, 1, isPositive ? 1 : 0);
        const attribution = {
            primaryCondition: conditions.length > 0 ? `${conditions[0].type}=${conditions[0].value}` : 'unknown',
            conditionConfidence: conditions.length > 0 ? conditions[0].matchScore : 0,
            sourceFiles: [],
            note: 'Config-conditioned correlation, not proven causation',
        };
        const lifecycle = {
            firstSeen: now,
            lastSeen: now,
            version: 1,
            history: [this.lifecycleTracker.createEntry('created', `Pattern: ${from} → ${to}`)],
        };
        const signals = { positive, negative, total: 1, lastSignal: now };
        const quality = this.qualityEngine.compute(signals, now, now, 1);
        const pattern = {
            patternId,
            category,
            description,
            from,
            to,
            conditions,
            confidence,
            signals,
            attribution,
            scope,
            survivedDays: 0,
            meta,
            lifecycle,
            quality,
            relationships: { related: [], conflicting: [], complementary: [], dependencies: [] },
            ranking: { score: 0, rank: 0, factors: { confidence: 0, quality: 0, usage: 0, recency: 0, acceptance: 0 } },
        };
        this.patterns.set(patternId, pattern);
        this.patternIndex.set(`${category}|${from}|${to}`, patternId);
        this.rebuildRelationships();
        this.rebuildRankings();
        return pattern;
    }
    updatePattern(patternId, isPositive, stepUsed, language) {
        const pattern = this.patterns.get(patternId);
        if (!pattern)
            throw new Error(`Pattern ${patternId} not found`);
        if (isPositive)
            pattern.signals.positive++;
        else
            pattern.signals.negative++;
        pattern.signals.total++;
        pattern.signals.lastSignal = Date.now();
        const acceptanceRate = pattern.signals.positive / Math.max(pattern.signals.total, 1);
        pattern.confidence = this.confidenceEngine.computeConfidence(pattern.signals.positive, pattern.signals.negative, pattern.signals.total, acceptanceRate);
        pattern.lifecycle.lastSeen = Date.now();
        pattern.lifecycle.history.push(this.lifecycleTracker.createEntry(isPositive ? 'accepted' : 'rejected'));
        pattern.lifecycle.version = this.lifecycleTracker.computeVersion(pattern.lifecycle.history);
        if (stepUsed && stepUsed !== 'none') {
            const source = (0, pattern_classifier_1.inferSource)(stepUsed);
            if (source !== pattern.meta.source) {
                pattern.meta.source = source;
            }
        }
        if (language) {
            pattern.meta.language = language;
        }
        pattern.quality = this.qualityEngine.compute(pattern.signals, pattern.lifecycle.firstSeen, pattern.lifecycle.lastSeen, pattern.lifecycle.version);
        this.rebuildRelationships();
        this.rebuildRankings();
        return pattern;
    }
    getPattern(patternId) {
        return this.patterns.get(patternId);
    }
    getAllPatterns() {
        return Array.from(this.patterns.values());
    }
    getPatternsByTier(tier) {
        return this.getAllPatterns().filter((p) => {
            const t = this.confidenceEngine.getTier(p.confidence);
            return t === tier;
        });
    }
    getPatternsAboveConfidence(threshold) {
        return this.getAllPatterns().filter((p) => p.confidence.mean >= threshold);
    }
    getPatternCount() {
        return this.patterns.size;
    }
    getTotalSignals() {
        let total = 0;
        for (const p of this.patterns.values()) {
            total += p.signals.total;
        }
        return total;
    }
    search(query) {
        return this.searchEngine.search(this.getAllPatterns(), query);
    }
    getRankedPatterns() {
        return this.rankingEngine.rank(this.getAllPatterns());
    }
    getValidationLog() {
        return this.validationLog;
    }
    exportTasteModel() {
        return {
            version: types_1.TASTE_MODEL_VERSION,
            lastUpdated: new Date().toISOString(),
            totalSignals: this.getTotalSignals(),
            patterns: this.getAllPatterns(),
        };
    }
    exportTasteMarkdown() {
        const model = this.exportTasteModel();
        const grouped = this.groupByCategory(model.patterns);
        let md = '# FIVO Cell — Your Taste Profile\n\n';
        md += `> Last updated: ${model.lastUpdated}\n`;
        md += `> Total signals: ${model.totalSignals}\n`;
        md += `> Patterns learned: ${model.patterns.length}\n\n`;
        for (const [category, patterns] of Object.entries(grouped)) {
            md += `## ${this.formatCategoryName(category)}\n\n`;
            for (const p of patterns) {
                const tier = this.confidenceEngine.getTier(p.confidence);
                md += `- ${p.description}. `;
                md += `Confidence: ${p.confidence.mean} `;
                md += `| Quality: ${p.quality.score}/100 `;
                md += `| Rank: #${p.ranking.rank || '-'} `;
                md += `| Signals: ${p.signals.positive}/${p.signals.total} `;
                md += `| Tier: ${tier}\n`;
            }
            md += '\n';
        }
        return md;
    }
    save() {
        const model = this.exportTasteModel();
        fs.writeFileSync(this.storePath, JSON.stringify(model, null, 2), 'utf-8');
        const mdPath = this.storePath.replace('cell.json', 'cell.md');
        fs.writeFileSync(mdPath, this.exportTasteMarkdown(), 'utf-8');
        const metaPath = this.storePath.replace('cell.json', 'cell-meta.json');
        let existingMeta = {};
        if (fs.existsSync(metaPath)) {
            try {
                existingMeta = JSON.parse(fs.readFileSync(metaPath, 'utf-8'));
            }
            catch { }
        }
        const meta = {
            ...existingMeta,
            version: types_1.TASTE_MODEL_VERSION,
            lastUpdated: model.lastUpdated,
            totalSignals: model.totalSignals,
            patternCount: model.patterns.length,
        };
        fs.writeFileSync(metaPath, JSON.stringify(meta, null, 2), 'utf-8');
    }
    clear() {
        this.patterns.clear();
        this.patternIndex.clear();
        this.validationLog = [];
        this.save();
    }
    rebuildRelationships() {
        const patterns = this.getAllPatterns();
        for (const p of patterns) {
            p.relationships = this.relationshipEngine.buildRelationships(p.patternId, p.category, p.from, p.to, patterns);
        }
    }
    rebuildRankings() {
        const ranked = this.rankingEngine.rank(this.getAllPatterns());
        for (const r of ranked) {
            this.patterns.set(r.patternId, r);
        }
    }
    findExistingPattern(category, from, to) {
        return this.patternIndex.get(`${category}|${from}|${to}`) || null;
    }
    load() {
        if (fs.existsSync(this.storePath)) {
            try {
                const data = fs.readFileSync(this.storePath, 'utf-8');
                const model = JSON.parse(data);
                for (const pattern of model.patterns) {
                    if (!pattern.patternId || !pattern.category || pattern.from === undefined || pattern.to === undefined)
                        continue;
                    pattern.meta = pattern.meta || { language: 'unknown', subcategory: 'general', complexity: 'low', risk: 'medium', source: 'manual' };
                    pattern.lifecycle = pattern.lifecycle || { firstSeen: Date.now(), lastSeen: Date.now(), version: 1, history: [] };
                    pattern.quality = pattern.quality || { score: 50, reuseRate: 0, successRate: 0, failureRate: 0, acceptanceRate: 0, daysSinceLastSignal: 0, age: 0 };
                    pattern.relationships = pattern.relationships || { related: [], conflicting: [], complementary: [], dependencies: [] };
                    pattern.ranking = pattern.ranking || { score: 0, rank: 0, factors: { confidence: 0, quality: 0, usage: 0, recency: 0, acceptance: 0 } };
                    this.patterns.set(pattern.patternId, pattern);
                    this.patternIndex.set(`${pattern.category}|${pattern.from}|${pattern.to}`, pattern.patternId);
                }
            }
            catch {
                this.patterns.clear();
            }
        }
    }
    groupByCategory(patterns) {
        const grouped = {};
        for (const p of patterns) {
            if (!grouped[p.category])
                grouped[p.category] = [];
            grouped[p.category].push(p);
        }
        return grouped;
    }
    formatCategoryName(category) {
        return category
            .split('_')
            .map((w) => w.charAt(0).toUpperCase() + w.slice(1))
            .join(' ');
    }
    ensureDirectory(dir) {
        if (!fs.existsSync(dir)) {
            fs.mkdirSync(dir, { recursive: true });
        }
    }
}
exports.PatternStore = PatternStore;
//# sourceMappingURL=pattern-store.js.map