"use strict";
/**
 * Feature Assembly Agent
 *
 * Combines generated components into complete working features
 * with actions, hooks, routes, and role-based permissions.
 */
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.FeatureAssemblyAgent = void 0;
const fs = __importStar(require("fs/promises"));
const path = __importStar(require("path"));
const chalk_1 = __importDefault(require("chalk"));
const AICore_1 = require("../../core/ai/AICore");
class FeatureAssemblyAgent {
    constructor(projectPath) {
        this.name = "FeatureAssemblyAgent";
        this.description = "Combines generated components into complete working features";
        this.personality = "systematic and thorough";
        this.llmProvider = "hybrid";
        this.expertise = [
            "feature-assembly",
            "role-based-access",
            "component-integration",
        ];
        this.projectPath = projectPath;
        this.aiCore = AICore_1.AICore.getInstance();
    }
    async run(context) {
        const startTime = Date.now();
        console.log(chalk_1.default.cyan("🔧 Feature Assembly Agent starting..."));
        try {
            // NEW: Load Living Context
            const livingContext = await this.aiCore.getLivingContext();
            // Step 1: Analyze components and group into features
            console.log(chalk_1.default.gray("  📋 Analyzing components and grouping into features..."));
            const featureGroups = await this.analyzeAndGroupComponents(context.components, context.contextFiles, livingContext || undefined);
            // Step 2: Generate feature bundles for each group
            console.log(chalk_1.default.gray("  🎯 Generating feature bundles..."));
            const features = [];
            const errors = [];
            const warnings = [];
            for (const group of featureGroups) {
                try {
                    const feature = await this.generateFeatureBundle(group, context);
                    features.push(feature);
                    console.log(chalk_1.default.green(`    ✓ Generated feature: ${feature.name}`));
                }
                catch (error) {
                    const errorMsg = `Failed to generate feature ${group.name}: ${error}`;
                    errors.push(errorMsg);
                    console.log(chalk_1.default.red(`    ✗ ${errorMsg}`));
                }
            }
            // Step 3: Apply role-based permissions
            console.log(chalk_1.default.gray("  🔐 Applying role-based permissions..."));
            const roleBasedFeatures = await this.applyRoleBasedPermissions(features, context.targetRole);
            // Step 4: Generate supporting files (actions, hooks, routes)
            console.log(chalk_1.default.gray("  📁 Generating supporting files..."));
            await this.generateSupportingFiles(roleBasedFeatures, context);
            // Step 5: Save feature bundles
            console.log(chalk_1.default.gray("  💾 Saving feature bundles..."));
            await this.saveFeatureBundles(roleBasedFeatures, context.outputPath);
            const processingTime = Date.now() - startTime;
            const result = {
                success: errors.length === 0,
                features: roleBasedFeatures,
                errors,
                warnings,
                metadata: {
                    totalFeatures: roleBasedFeatures.length,
                    totalComponents: roleBasedFeatures.reduce((sum, f) => sum + f.components.length, 0),
                    totalActions: roleBasedFeatures.reduce((sum, f) => sum + f.actions.length, 0),
                    totalHooks: roleBasedFeatures.reduce((sum, f) => sum + f.hooks.length, 0),
                    totalRoutes: roleBasedFeatures.reduce((sum, f) => sum + f.routes.length, 0),
                    processingTime,
                },
            };
            console.log(chalk_1.default.green(`✅ Feature Assembly completed in ${processingTime}ms`));
            console.log(chalk_1.default.blue(`   Generated ${result.metadata.totalFeatures} features`));
            console.log(chalk_1.default.blue(`   Generated ${result.metadata.totalComponents} components`));
            console.log(chalk_1.default.blue(`   Generated ${result.metadata.totalActions} actions`));
            console.log(chalk_1.default.blue(`   Generated ${result.metadata.totalHooks} hooks`));
            console.log(chalk_1.default.blue(`   Generated ${result.metadata.totalRoutes} routes`));
            return result;
        }
        catch (error) {
            console.log(chalk_1.default.red(`❌ Feature Assembly failed: ${error}`));
            return {
                success: false,
                features: [],
                errors: [error instanceof Error ? error.message : String(error)],
                warnings: [],
                metadata: {
                    totalFeatures: 0,
                    totalComponents: 0,
                    totalActions: 0,
                    totalHooks: 0,
                    totalRoutes: 0,
                    processingTime: Date.now() - startTime,
                },
            };
        }
    }
    async analyzeAndGroupComponents(components, contextFiles, livingContext) {
        const prompt = `
Analyze the following components and group them into logical features based on functionality and purpose.

Components:
${components.map((c) => `- ${c}`).join("\n")}

Context Files:
${JSON.stringify(contextFiles, null, 2)}

Group the components into features that work together to provide complete functionality. Each feature should have:
- A clear purpose and scope
- Related components that work together
- A logical name and description

Return a JSON array of component groups with this structure:
[
  {
    "name": "feature-name",
    "description": "What this feature does",
    "components": ["component1", "component2"],
    "category": "authentication|user-management|content|settings|analytics|communication",
    "priority": "high|medium|low"
  }
]
`;
        try {
            const response = await this.aiCore.generateText(prompt);
            return JSON.parse(response || "[]");
        }
        catch (error) {
            // Fallback to rule-based grouping
            return this.fallbackComponentGrouping(components);
        }
    }
    fallbackComponentGrouping(components) {
        const groups = [];
        const componentMap = new Map();
        // Rule-based grouping patterns
        const patterns = {
            authentication: ["login", "signup", "auth", "password", "session"],
            "user-management": ["user", "profile", "account", "member"],
            content: ["post", "article", "blog", "content", "page"],
            settings: ["setting", "config", "preference", "option"],
            analytics: ["analytics", "stats", "metric", "dashboard", "chart"],
            communication: ["message", "chat", "notification", "email", "comment"],
        };
        // Group components by patterns
        for (const component of components) {
            const lowerComponent = component.toLowerCase();
            let assigned = false;
            for (const [category, keywords] of Object.entries(patterns)) {
                if (keywords.some((keyword) => lowerComponent.includes(keyword))) {
                    if (!componentMap.has(category)) {
                        componentMap.set(category, []);
                    }
                    componentMap.get(category).push(component);
                    assigned = true;
                    break;
                }
            }
            if (!assigned) {
                if (!componentMap.has("general")) {
                    componentMap.set("general", []);
                }
                componentMap.get("general").push(component);
            }
        }
        // Convert to ComponentGroup format
        for (const [category, comps] of componentMap) {
            groups.push({
                name: category,
                description: `Components related to ${category}`,
                components: comps,
                category: category,
                priority: "medium",
            });
        }
        return groups;
    }
    async generateFeatureBundle(group, context) {
        const prompt = `
Generate a complete feature bundle for the following component group:

Feature: ${group.name}
Description: ${group.description}
Components: ${group.components.join(", ")}
Category: ${group.category}
Target Role: ${context.targetRole}

Context Files:
${JSON.stringify(context.contextFiles, null, 2)}

Design Manifest:
${JSON.stringify(context.designManifest, null, 2)}

Generate a complete feature bundle with:
1. Server actions for CRUD operations
2. Custom hooks for data management
3. API routes for backend operations
4. Database schema and queries
5. Role-based permissions
6. TypeScript types

Return a JSON object matching the FeatureBundle interface:
{
  "name": "feature-name",
  "description": "Feature description",
  "role": "admin|user|guest",
  "components": ["component1", "component2"],
  "types": ["Type1", "Type2"],
  "actions": [...],
  "hooks": [...],
  "routes": [...],
  "database": {...},
  "permissions": [...],
  "metadata": {...}
}
`;
        try {
            const response = await this.aiCore.generateText(prompt);
            const bundle = JSON.parse(response || "{}");
            // Add metadata
            bundle.metadata = {
                createdAt: new Date().toISOString(),
                updatedAt: new Date().toISOString(),
                version: "1.0.0",
                dependencies: this.extractDependencies(bundle),
            };
            return bundle;
        }
        catch (error) {
            // Fallback to template-based generation
            return this.generateFeatureBundleFromTemplate(group, context);
        }
    }
    generateFeatureBundleFromTemplate(group, context) {
        // Find matching template
        const template = context.featureTemplates.find((t) => t.category === group.category);
        if (!template) {
            // Generate basic template
            return this.generateBasicFeatureBundle(group, context);
        }
        // Convert template to feature bundle
        return {
            name: group.name,
            description: group.description,
            role: context.targetRole,
            components: group.components,
            types: template.components.map((c) => c.name),
            actions: template.actions.map((a) => ({
                name: a.name,
                description: a.description,
                file: `actions/${a.name}.ts`,
                function: a.name,
                parameters: a.parameters,
                returnType: a.returnType,
                permissions: a.permissions,
                validation: undefined,
            })),
            hooks: template.hooks.map((h) => ({
                name: h.name,
                description: h.description,
                file: `hooks/${h.name}.ts`,
                function: h.name,
                parameters: h.parameters,
                returnType: h.returnType,
                dependencies: h.dependencies,
            })),
            routes: template.routes.map((r) => ({
                path: r.path,
                method: r.method,
                description: r.description,
                file: `app/api${r.path}/route.ts`,
                function: r.path.replace(/\//g, "_").replace(/\[.*?\]/g, "id"),
                parameters: r.parameters,
                responseType: r.responseType,
                permissions: r.permissions,
                middleware: undefined,
            })),
            database: {
                schema: JSON.stringify(template.database, null, 2),
                queries: template.database.tables.map((t) => `SELECT * FROM ${t.name}`),
                mutations: template.database.tables.map((t) => `INSERT INTO ${t.name}`),
            },
            permissions: template.permissions.map((p) => ({
                id: `${group.name}-${p.role}-${p.resource}`,
                resource: p.resource,
                action: p.actions[0],
                conditions: p.conditions,
                description: `Permission for ${p.role} on ${p.resource}`,
            })),
            metadata: {
                createdAt: new Date().toISOString(),
                updatedAt: new Date().toISOString(),
                version: "1.0.0",
                dependencies: template.dependencies,
            },
        };
    }
    generateBasicFeatureBundle(group, context) {
        return {
            name: group.name,
            description: group.description,
            role: context.targetRole,
            components: group.components,
            types: [`${group.name}Data`, `${group.name}Form`],
            actions: [
                {
                    name: `get${group.name}`,
                    description: `Get ${group.name} data`,
                    file: `actions/${group.name}.ts`,
                    function: `get${group.name}`,
                    parameters: [],
                    returnType: "Promise<any[]>",
                    permissions: [`${group.name}:read`],
                },
            ],
            hooks: [
                {
                    name: `use${group.name}`,
                    description: `Hook for ${group.name} data`,
                    file: `hooks/${group.name}.ts`,
                    function: `use${group.name}`,
                    parameters: [],
                    returnType: "any",
                    dependencies: [],
                },
            ],
            routes: [
                {
                    path: `/api/${group.name}`,
                    method: "GET",
                    description: `Get ${group.name} data`,
                    file: `app/api/${group.name}/route.ts`,
                    function: "GET",
                    parameters: [],
                    responseType: "any[]",
                    permissions: [`${group.name}:read`],
                },
            ],
            database: {
                schema: `CREATE TABLE ${group.name} (id TEXT PRIMARY KEY, data JSONB);`,
                queries: [`SELECT * FROM ${group.name}`],
                mutations: [`INSERT INTO ${group.name} (id, data) VALUES (?, ?)`],
            },
            permissions: [
                {
                    id: `${group.name}-${context.targetRole}-read`,
                    resource: group.name,
                    action: "read",
                    description: `Read access to ${group.name}`,
                },
            ],
            metadata: {
                createdAt: new Date().toISOString(),
                updatedAt: new Date().toISOString(),
                version: "1.0.0",
                dependencies: [],
            },
        };
    }
    async applyRoleBasedPermissions(features, targetRole) {
        // Apply role-based filtering and permissions
        return features.map((feature) => ({
            ...feature,
            role: targetRole,
            permissions: feature.permissions.filter((p) => this.hasPermissionForRole(p, targetRole)),
        }));
    }
    hasPermissionForRole(permission, role) {
        // Role hierarchy: admin > moderator > editor > user > guest
        const roleLevels = {
            admin: 5,
            moderator: 4,
            editor: 3,
            user: 2,
            guest: 1,
        };
        const permissionLevels = {
            manage: 5,
            create: 4,
            update: 3,
            delete: 3,
            approve: 4,
            reject: 4,
            export: 2,
            import: 3,
            read: 1,
        };
        const roleLevel = roleLevels[role] || 1;
        const permissionLevel = permissionLevels[permission.action] || 1;
        return roleLevel >= permissionLevel;
    }
    async generateSupportingFiles(features, context) {
        for (const feature of features) {
            // Generate actions
            await this.generateActions(feature, context);
            // Generate hooks
            await this.generateHooks(feature, context);
            // Generate routes
            await this.generateRoutes(feature, context);
            // Generate types
            await this.generateTypes(feature, context);
        }
    }
    async generateActions(feature, context) {
        const actionsDir = path.join(context.outputPath, "actions");
        await fs.mkdir(actionsDir, { recursive: true });
        for (const action of feature.actions) {
            const actionCode = this.generateActionCode(action, feature);
            const actionFile = path.join(actionsDir, `${action.name}.ts`);
            await fs.writeFile(actionFile, actionCode);
        }
    }
    generateActionCode(action, feature) {
        return `/**
 * ${action.description}
 */

export async function ${action.function}(${action.parameters
            .map((p) => `${p.name}: ${p.type}`)
            .join(", ")}): Promise<${action.returnType}> {
  // TODO: Implement ${action.name}
  throw new Error('Not implemented');
}
`;
    }
    async generateHooks(feature, context) {
        const hooksDir = path.join(context.outputPath, "hooks");
        await fs.mkdir(hooksDir, { recursive: true });
        for (const hook of feature.hooks) {
            const hookCode = this.generateHookCode(hook, feature);
            const hookFile = path.join(hooksDir, `${hook.name}.ts`);
            await fs.writeFile(hookFile, hookCode);
        }
    }
    generateHookCode(hook, feature) {
        return `/**
 * ${hook.description}
 */

export function ${hook.function}(${hook.parameters
            .map((p) => `${p.name}: ${p.type}`)
            .join(", ")}): ${hook.returnType} {
  // TODO: Implement ${hook.name}
  throw new Error('Not implemented');
}
`;
    }
    async generateRoutes(feature, context) {
        for (const route of feature.routes) {
            const routeDir = path.dirname(path.join(context.outputPath, route.file));
            await fs.mkdir(routeDir, { recursive: true });
            const routeCode = this.generateRouteCode(route, feature);
            const routeFile = path.join(context.outputPath, route.file);
            await fs.writeFile(routeFile, routeCode);
        }
    }
    generateRouteCode(route, feature) {
        return `/**
 * ${route.description}
 */

import { NextRequest, NextResponse } from 'next/server';

export async function ${route.method}(request: NextRequest) {
  // TODO: Implement ${route.path} ${route.method}
  return NextResponse.json({ error: 'Not implemented' }, { status: 501 });
}
`;
    }
    async generateTypes(feature, context) {
        const typesDir = path.join(context.outputPath, "types");
        await fs.mkdir(typesDir, { recursive: true });
        const typesCode = this.generateTypesCode(feature);
        const typesFile = path.join(typesDir, `${feature.name}.ts`);
        await fs.writeFile(typesFile, typesCode);
    }
    generateTypesCode(feature) {
        return `/**
 * Types for ${feature.name} feature
 */

export interface ${feature.name}Data {
  id: string;
  // TODO: Add specific fields
}

export interface ${feature.name}Form {
  // TODO: Add form fields
}

export interface ${feature.name}CreateData {
  // TODO: Add creation fields
}

export interface ${feature.name}UpdateData {
  // TODO: Add update fields
}
`;
    }
    async saveFeatureBundles(features, outputPath) {
        const bundlesDir = path.join(outputPath, ".mycontext", "feature-bundles");
        await fs.mkdir(bundlesDir, { recursive: true });
        for (const feature of features) {
            const bundleFile = path.join(bundlesDir, `${feature.name}.json`);
            await fs.writeFile(bundleFile, JSON.stringify(feature, null, 2));
        }
    }
    extractDependencies(bundle) {
        const deps = new Set();
        // Extract from actions
        bundle.actions.forEach((action) => {
            if (action.validation?.schema)
                deps.add("zod");
        });
        // Extract from hooks
        bundle.hooks.forEach((hook) => {
            hook.dependencies.forEach((dep) => deps.add(dep));
        });
        return Array.from(deps);
    }
}
exports.FeatureAssemblyAgent = FeatureAssemblyAgent;
//# sourceMappingURL=FeatureAssemblyAgent.js.map