"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.ScaffoldAgent = void 0;
const spinner_1 = require("../utils/spinner");
const fileSystem_1 = require("../utils/fileSystem");
const chalk_1 = __importDefault(require("chalk"));
const child_process_1 = require("child_process");
const path = __importStar(require("path"));
const fs = __importStar(require("fs-extra"));
class ScaffoldAgent {
    constructor() {
        this.fs = new fileSystem_1.FileSystemManager();
        this.spinner = new spinner_1.EnhancedSpinner("Refining architecture...");
    }
    /**
     * Deterministically scaffold the project from the MegaContext
     */
    async scaffold(context) {
        console.log(chalk_1.default.blue(`\n🚀 Scaling up to 100% deterministic scaffold for: ${context.project.name}\n`));
        const projectPath = path.resolve(process.cwd(), context.project.name);
        // Visual Roadmap
        console.log(chalk_1.default.cyan("\n📋 Execution Plan:"));
        console.log(chalk_1.default.gray("  1. Bootstrap Next.js + InstantDB"));
        console.log(chalk_1.default.gray("  2. Install InstantDB SDK"));
        console.log(chalk_1.default.gray("  3. Generate InstantDB Schema"));
        console.log(chalk_1.default.gray("  4. Generate Route Structure"));
        console.log(chalk_1.default.gray("  5. Persist Living Brain (.mycontext)"));
        console.log("");
        // 1. Framework Scaffold (Next.js)
        if (!fs.existsSync(projectPath)) {
            this.spinner.updateText("[1/5] Bootstrapping Next.js + InstantDB...");
            this.spinner.start();
            try {
                // Using a more deterministic install command (pnpm dlx create-next-app)
                // We use --no-eslint --no-tailwind --no-src-dir etc to have full control? 
                // For now, let's stick to standard recommended setup but fast
                (0, child_process_1.execSync)(`pnpm dlx create-next-app@latest ${context.project.name} --typescript --tailwind --eslint --app --no-src-dir --import-alias "@/*" --use-pnpm`, {
                    stdio: "ignore"
                });
                this.spinner.success({ text: "[1/5] Next.js shell created." });
            }
            catch (e) {
                this.spinner.error({ text: "Failed to scaffold Next.js app." });
                throw e;
            }
        }
        else {
            console.log(chalk_1.default.yellow("  [1/5] Directory exists, skipping scaffold."));
        }
        // 2. Install InstantDB
        this.spinner.updateText("[2/5] Installing InstantDB SDK...");
        this.spinner.start();
        (0, child_process_1.execSync)("pnpm add @instantdb/react @instantdb/admin", { cwd: projectPath, stdio: "ignore" });
        this.spinner.success({ text: "[2/5] InstantDB SDK installed." });
        // 3. Generate Schema
        this.spinner.updateText("[3/5] Generating InstantDB Schema...");
        this.spinner.start();
        await this.generateSchemaFile(projectPath, context);
        this.spinner.success({ text: "[3/5] Schema generated from MegaContext." });
        // 4. Generate Routes & Pages
        this.spinner.updateText("[4/5] Generating Route Structure...");
        this.spinner.start();
        await this.generateRoutes(projectPath, context);
        this.spinner.success({ text: "[4/5] Routes & Layouts generated." });
        // 5. Persist "Living Brain"
        this.spinner.updateText("[5/5] Initializing Living Brain (.mycontext)...");
        this.spinner.start();
        await this.saveContext(projectPath, context);
        await this.createAlign(projectPath);
        await this.createReadme(projectPath, context);
        await this.createEnvFile(projectPath);
        this.spinner.success({ text: "[5/5] Context, Utils, & .env saved." });
        console.log(chalk_1.default.green(`\n✅ Project "${context.project.name}" is ready!`));
        console.log(chalk_1.default.gray(`   cd ${context.project.name} && pnpm dev`));
    }
    /**
     * Generate instant.schema.ts
     */
    async generateSchemaFile(projectPath, context) {
        // This would actually generate the full TS file content based on context.database.entities
        // For prototype, we generate a stub
        const schemaContent = `
import { i } from "@instantdb/react";

export const graph = i.graph(
  "${context.project.id}",
  {
    ${Object.entries(context.database.entities).map(([name, def]) => `${name}: i.entity({
      ${Object.keys(def.fields).map(f => `${f}: i.string()`).join(",\n      ")}
    })`).join(",\n    ")}
  }
);
    `;
        await fs.ensureDir(path.join(projectPath, "lib"));
        await fs.writeFile(path.join(projectPath, "lib", "instant.schema.ts"), schemaContent);
    }
    /**
     * Generate Next.js App Router structure
     */
    async generateRoutes(projectPath, context) {
        const appDir = path.join(projectPath, "app");
        for (const [routePath, routeNode] of Object.entries(context.routing.routes)) {
            if (routeNode.type === "page") {
                const relativePath = routePath === "/" ? "" : routePath.slice(1); // remove leading slash
                const targetDir = path.join(appDir, relativePath);
                await fs.ensureDir(targetDir);
                const pageContent = `
export default function Page() {
  return (
    <div className="container mx-auto py-10">
      <h1 className="text-4xl font-bold">${routeNode.ui?.title || "Page"}</h1>
      <p className="mt-4 text-muted-foreground">${routeNode.ui?.description || ""}</p>
      {/* Components: ${routeNode.ui?.components?.map(c => c.name).join(", ")} */}
    </div>
  );
}
            `;
                await fs.writeFile(path.join(targetDir, "page.tsx"), pageContent);
            }
        }
    }
    // ... existing methods ...
    /**
     * Create .env file with API keys
     */
    async createEnvFile(projectPath) {
        // Collect specific keys we care about
        const keys = [];
        if (process.env.GEMINI_API_KEY)
            keys.push(`GEMINI_API_KEY=${process.env.GEMINI_API_KEY}`);
        if (process.env.GOOGLE_API_KEY)
            keys.push(`GOOGLE_API_KEY=${process.env.GOOGLE_API_KEY}`);
        if (process.env.OPENROUTER_API_KEY)
            keys.push(`OPENROUTER_API_KEY=${process.env.OPENROUTER_API_KEY}`);
        // Default InstantDB App ID (Placeholder)
        keys.push(`NEXT_PUBLIC_INSTANT_APP_ID=${process.env.NEXT_PUBLIC_INSTANT_APP_ID || "YOUR_APP_ID_HERE"}`);
        if (keys.length > 0) {
            await fs.writeFile(path.join(projectPath, ".env"), keys.join("\n"));
        }
    }
    /**
     * Save the MegaContext to .mycontext/context.json
     */
    async saveContext(projectPath, context) {
        const contextDir = path.join(projectPath, ".mycontext");
        await fs.ensureDir(contextDir);
        await fs.writeJSON(path.join(contextDir, "context.json"), context, { spaces: 2 });
    }
    /**
     * Create the .mycontext/ALIGN file
     */
    async createAlign(projectPath) {
        const alignContent = `# MyContext Alignment Guard [SYNC]
Any changes to code, architecture, or features MUST be synchronized with:
1. \`.mycontext/context.json\` (Source of Truth / Living Brain)
2. \`README.md\` (Human-facing orientation & usage)

[PHILOSOPHY: DETERMINISTIC SCAFFOLDING]:
- **Next.js + InstantDB First**: We are built for Next.js full-stack projects using InstantDB as the backend.
- **Mega Context (100% Knowledge)**:
- Before ANY code is generated, the MegaContext must be 100% populated.

[PROJECT SCANNER — CONTEXT SYNC]:
- Run \`mycontext scan --assess\` to compare actual code against planned context.json.
- Identifies routes/components/entities in code but missing from context, and vice versa.
- Use during development to keep context.json aligned with reality.
`;
        const contextDir = path.join(projectPath, ".mycontext");
        await fs.ensureDir(contextDir);
        await fs.writeFile(path.join(contextDir, "ALIGN"), alignContent);
    }
    /**
     * Generate a README.md based on the context
     */
    async createReadme(projectPath, context) {
        const readmeContent = `# ${context.project.name}

${context.project.description}

## Tech Stack
- **Framework**: Next.js (App Router)
- **Backend**: InstantDB
- **Styling**: TailwindCSS + ShadCN

## Computed Architecture
- **Roles**: ${context.auth.roles.map(r => r.name).join(", ")}
- **Entities**: ${Object.keys(context.database.entities).join(", ")}
- **Routes**: ${Object.keys(context.routing.routes).join(", ")}

## Getting Started

\`\`\`bash
pnpm install
pnpm dev
\`\`\`

Generated by MyContext CLI 🚀
`;
        await fs.writeFile(path.join(projectPath, "README.md"), readmeContent);
    }
}
exports.ScaffoldAgent = ScaffoldAgent;
//# sourceMappingURL=ScaffoldAgent.js.map