"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;
    };
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.ContextSyncer = void 0;
/**
 * ContextSyncer — Autonomous context.json + README updater
 *
 * The "self-recontextualization" engine:
 * 1. Scan the real project (via ProjectScanner)
 * 2. LLM assesses drift between code and context.json
 * 3. Deep merge suggestions into context.json
 * 4. LLM generates README content from updated context
 * 5. Write both files
 */
const fs = __importStar(require("fs-extra"));
const path = __importStar(require("path"));
const chalk_1 = __importDefault(require("chalk"));
const ProjectScanner_1 = require("./ProjectScanner");
const contextRenderer_1 = require("../utils/contextRenderer");
const AICore_1 = require("../core/ai/AICore");
const deepMerge_1 = require("../utils/deepMerge");
const unified_context_1 = require("../types/unified-context");
const ContextEnrichmentService_1 = require("./ContextEnrichmentService");
class ContextSyncer {
    constructor(projectRoot = process.cwd()) {
        this.projectRoot = projectRoot;
        this.scanner = new ProjectScanner_1.ProjectScanner(projectRoot);
    }
    /**
     * Sync context.json: scan → assess → deep merge
     */
    async syncContext(snapshot, options = {}) {
        const contextPath = path.join(this.projectRoot, ".mycontext", "context.json");
        // Load existing context
        let existingContext = {};
        try {
            if (await fs.pathExists(contextPath)) {
                existingContext = await fs.readJson(contextPath);
            }
        }
        catch {
            // Start fresh if corrupted
        }
        // Scan if not provided
        if (!snapshot) {
            snapshot = await this.scanner.scan();
        }
        // Assess via LLM
        console.log(chalk_1.default.blue("\n🧠 Assessing progress against Living Brain...\n"));
        const report = await this.scanner.assessProgress(snapshot, existingContext);
        this.scanner.displayReport(report);
        if (report.overallProgress < 0) {
            return { contextUpdated: false, report, contextDiff: "LLM assessment failed" };
        }
        // Deep merge suggestions
        const hasMerge = Object.keys(report.suggestedContextMerge).length > 0;
        if (!hasMerge) {
            return { contextUpdated: false, report, contextDiff: "No changes suggested" };
        }
        const merged = (0, deepMerge_1.deepMerge)(existingContext, report.suggestedContextMerge);
        // Grounding Protection: Preserve description if it's already grounded
        const existingDesc = existingContext.metadata?.projectConfig?.description || existingContext.project?.description || "";
        if (existingDesc.includes("GROUNDING DOC")) {
            if (merged.metadata?.projectConfig) {
                merged.metadata.projectConfig.description = existingDesc;
            }
            if (merged.project) {
                merged.project.description = existingDesc;
            }
        }
        // Update scan memory
        if (!merged.brain)
            merged.brain = {};
        if (!merged.brain.memory)
            merged.brain.memory = {};
        merged.brain.memory.lastSync = {
            syncedAt: new Date().toISOString(),
            totalFiles: snapshot.stats.totalFiles,
            totalDirs: snapshot.stats.totalDirs,
            overallProgress: report.overallProgress,
            diffsFound: report.diffs.length,
        };
        const diffSummary = report.diffs
            .map((d) => `  ${d.type === "missing_in_context" ? "+" : d.type === "missing_in_code" ? "-" : "~"} [${d.category}] ${d.description}`)
            .join("\n");
        if (options.dryRun) {
            console.log(chalk_1.default.yellow("\n🔍 DRY RUN — would apply these changes:"));
            console.log(chalk_1.default.gray(diffSummary));
            return { contextUpdated: false, report, contextDiff: diffSummary };
        }
        // Write
        await fs.ensureDir(path.dirname(contextPath));
        await fs.writeJson(contextPath, merged, { spaces: 2 });
        // Refresh Markdown views to keep them in sync with the brain
        await this.refreshMarkdownViews(merged);
        // Trigger background enrichment if there are context gaps
        const enrichment = new ContextEnrichmentService_1.ContextEnrichmentService(this.projectRoot);
        if (await enrichment.needsEnrichment(merged)) {
            await enrichment.triggerBackgroundEnrichment();
        }
        return { contextUpdated: true, report, contextDiff: diffSummary };
    }
    /**
     * Sync README: read context.json → LLM generate section → write between markers
     */
    async syncReadme(options = {}) {
        const readmePath = path.join(this.projectRoot, "README.md");
        const contextPath = path.join(this.projectRoot, ".mycontext", "context.json");
        if (!(await fs.pathExists(readmePath))) {
            return { readmeUpdated: false, readmeDiff: "No README.md found" };
        }
        if (!(await fs.pathExists(contextPath))) {
            return { readmeUpdated: false, readmeDiff: "No context.json found" };
        }
        const readme = await fs.readFile(readmePath, "utf-8");
        const context = await fs.readJson(contextPath);
        const summary = (0, unified_context_1.getContextSummary)(context);
        const START_MARKER = "<!-- mycontext:start -->";
        const END_MARKER = "<!-- mycontext:end -->";
        const startIdx = readme.indexOf(START_MARKER);
        const endIdx = readme.indexOf(END_MARKER);
        if (startIdx === -1 || endIdx === -1) {
            console.log(chalk_1.default.yellow("⚠️  No MyContext markers in README. Add these to enable auto-sync:"));
            console.log(chalk_1.default.cyan(`   ${START_MARKER}`));
            console.log(chalk_1.default.cyan(`   ${END_MARKER}`));
            return { readmeUpdated: false, readmeDiff: "No markers found in README" };
        }
        // Generate content via LLM
        const ai = this.getAICore();
        // Construct a richer prompt that encourages specificity
        const prompt = `Generate a concise, professional markdown section for a README based on this project context.
    
CONTEXT:
Project Name: ${summary.name}
Description: ${summary.description || "A modern web application"}
Entities: ${summary.entities.length > 0 ? summary.entities.join(", ") : "User, Project"}
Routes: ${summary.routes.length > 0 ? summary.routes.join(", ") : "Dashboard, Profile, Settings"}
Capabilities: ${summary.capabilities.length > 0 ? summary.capabilities.join(", ") : "Authentication, Data Management"}
Tech Stack: ${context.project?.techStack ? context.project.techStack.join(", ") : "Next.js, TypeScript, Tailwind CSS"}

INSTRUCTIONS:
1. Write a 3-section summary: Overview, Key Features, Tech Stack.
2. DO NOT use placeholders like "[Insert text here]" or "[Unknown]". If a detail is missing, infer it from the context or generic web app standards (e.g., "Built with modern web technologies").
3. Make it sound professional and "shipped".
4. Return ONLY the markdown content (no fences).

Example format:
## Overview
[Concise description of what the app does]

## Key Features
- **Feature 1**: Description
- **Feature 2**: Description

## Tech Stack
- Stack item 1
- Stack item 2
`;
        try {
            let newContent = await ai.generateText(prompt);
            newContent = newContent.replace(/^```[a-z]*\n?/gm, "").replace(/```$/gm, "").trim();
            const before = readme.substring(0, startIdx + START_MARKER.length);
            const after = readme.substring(endIdx);
            const updated = `${before}\n\n${newContent}\n\n${after}`;
            if (options.dryRun) {
                console.log(chalk_1.default.yellow("\n🔍 DRY RUN — README would be updated with:"));
                console.log(chalk_1.default.gray(newContent.substring(0, 300) + "..."));
                return { readmeUpdated: false, readmeDiff: newContent.substring(0, 200) };
            }
            await fs.writeFile(readmePath, updated, "utf-8");
            console.log(chalk_1.default.green("✅ README.md updated between markers!"));
            return { readmeUpdated: true, readmeDiff: `Updated ${newContent.split("\n").length} lines` };
        }
        catch (error) {
            console.log(chalk_1.default.red(`❌ README sync failed: ${error.message}`));
            return { readmeUpdated: false, readmeDiff: `Error: ${error.message}` };
        }
    }
    /**
     * Sync everything: context.json + README
     */
    async syncAll(options = {}) {
        console.log(chalk_1.default.blue("📂 Scanning project structure...\n"));
        const snapshot = await this.scanner.scan();
        this.scanner.displaySnapshot(snapshot);
        const contextResult = await this.syncContext(snapshot, options);
        const readmeResult = await this.syncReadme(options);
        // Add explicit next steps for the user
        console.log(chalk_1.default.cyan("\n🚀 Next Steps:"));
        if (contextResult.report && contextResult.report.diffs.length > 0) {
            console.log(chalk_1.default.white("  • Review the sync suggestions above."));
            console.log(chalk_1.default.white("  • Run 'mycontext generate context' to refine the Living Brain further."));
        }
        else {
            console.log(chalk_1.default.white("  • Your context is in sync! You can now start building features."));
            console.log(chalk_1.default.white("  • Try: mycontext agent \"add a blog page\""));
        }
        return {
            contextUpdated: contextResult.contextUpdated,
            readmeUpdated: readmeResult.readmeUpdated,
            report: contextResult.report,
            contextDiff: contextResult.contextDiff,
            readmeDiff: readmeResult.readmeDiff,
        };
    }
    /**
     * Refresh the 4 canonical Markdown views in .mycontext/
     */
    async refreshMarkdownViews(context) {
        const outputDir = path.join(this.projectRoot, ".mycontext");
        await fs.ensureDir(outputDir);
        const renders = [
            { name: "01-prd.md", content: contextRenderer_1.ContextRenderer.renderPRD(context) },
            { name: "02-technical-specs.md", content: contextRenderer_1.ContextRenderer.renderTechnicalSpecs(context) },
            { name: "03-brand-guide.md", content: contextRenderer_1.ContextRenderer.renderBrandGuide(context) },
            { name: "04-user-flows.md", content: contextRenderer_1.ContextRenderer.renderUserFlows(context) },
            { name: "05-evolution-history.md", content: contextRenderer_1.ContextRenderer.renderEvolutionHistory(context) },
        ];
        for (const render of renders) {
            await fs.writeFile(path.join(outputDir, render.name), render.content);
        }
        console.log(chalk_1.default.gray("   • Human-readable views refreshed in .mycontext/"));
        // Render specifications if present in context
        if (context.specifications && typeof context.specifications === "object") {
            const specsDir = path.join(outputDir, "specs");
            await fs.ensureDir(specsDir);
            for (const [specName, spec] of Object.entries(context.specifications)) {
                if (!spec || typeof spec !== "object")
                    continue;
                const featureDir = path.join(specsDir, specName);
                await fs.ensureDir(featureDir);
                await fs.writeFile(path.join(featureDir, "requirements.md"), contextRenderer_1.ContextRenderer.renderSpecRequirements(specName, spec));
                await fs.writeFile(path.join(featureDir, "design.md"), contextRenderer_1.ContextRenderer.renderSpecDesign(specName, spec));
                await fs.writeFile(path.join(featureDir, "tasks.md"), contextRenderer_1.ContextRenderer.renderSpecTasks(specName, spec));
            }
            console.log(chalk_1.default.gray("   • Human-readable specifications refreshed in .mycontext/specs/"));
        }
    }
    getAICore() {
        let aiCore;
        try {
            aiCore = AICore_1.AICore.getInstance();
        }
        catch {
            aiCore = AICore_1.AICore.getInstance({
                fallbackEnabled: true,
                workingDirectory: this.projectRoot,
            });
        }
        // Ensure providers are refreshed to pick up latest env vars
        aiCore.forceRefresh();
        return aiCore;
    }
}
exports.ContextSyncer = ContextSyncer;
//# sourceMappingURL=ContextSyncer.js.map