/**
 * Role Definition Service
 *
 * This service provides methods for managing agent role definitions.
 * Role definitions store system prompts and behavioral configurations
 * for agents, enabling consistent agent behavior across the workspace.
 *
 * Key features:
 * - Create role definitions with system prompts stored as Documents
 * - Update role definitions (creates new Document versions for prompt changes)
 * - Query role definitions by various criteria
 * - Link role definitions to agents
 *
 * @module
 */
import { ContentType, createDocument, createTimestamp } from '@stoneforge/core';
import { isAgentRoleDefinition, ROLE_DEFINITION_TAGS, generateRoleDefinitionTags, } from '../types/index.js';
// ============================================================================
// Constants
// ============================================================================
/**
 * Metadata key for storing role definition data in the Document
 */
const ROLE_DEF_META_KEY = 'roleDefinition';
/**
 * Content type used for role definition storage
 */
const ROLE_DEF_CONTENT_TYPE = ContentType.JSON;
// ============================================================================
// Role Definition Service Implementation
// ============================================================================
/**
 * Implementation of the Role Definition Service
 */
export class RoleDefinitionServiceImpl {
    api;
    constructor(api) {
        this.api = api;
    }
    async createRoleDefinition(input) {
        const now = createTimestamp();
        // Create the system prompt document first
        const systemPromptDoc = await createDocument({
            contentType: ContentType.MARKDOWN,
            content: input.systemPrompt,
            createdBy: input.createdBy,
            tags: [
                ROLE_DEFINITION_TAGS.AGENT_PROMPT,
                `${ROLE_DEFINITION_TAGS.ROLE_PREFIX}${input.role}`,
            ],
            metadata: {
                purpose: 'agent-system-prompt',
                role: input.role,
            },
        });
        // Save the system prompt document
        const savedPromptDoc = await this.api.create(systemPromptDoc);
        // Build the role definition based on role type
        let definition;
        const baseDefinition = {
            name: input.name,
            description: input.description,
            systemPromptRef: savedPromptDoc.id,
            maxConcurrentTasks: input.maxConcurrentTasks ?? 1,
            behaviors: input.behaviors,
            tags: input.tags,
            createdAt: now,
            createdBy: input.createdBy,
            updatedAt: now,
        };
        switch (input.role) {
            case 'director':
                definition = {
                    ...baseDefinition,
                    role: 'director',
                };
                break;
            case 'worker':
                definition = {
                    ...baseDefinition,
                    role: 'worker',
                    workerMode: input.workerMode,
                };
                break;
            case 'steward':
                definition = {
                    ...baseDefinition,
                    role: 'steward',
                    stewardFocus: input.stewardFocus,
                };
                break;
            default:
                throw new Error(`Unknown role type: ${input.role}`);
        }
        // Create the role definition document
        const roleDefDoc = await createDocument({
            contentType: ROLE_DEF_CONTENT_TYPE,
            content: JSON.stringify(definition, null, 2),
            createdBy: input.createdBy,
            tags: generateRoleDefinitionTags(input.role, input.tags),
            metadata: {
                [ROLE_DEF_META_KEY]: definition,
                systemPromptDocId: savedPromptDoc.id,
            },
        });
        // Save the role definition document
        const savedRoleDefDoc = await this.api.create(roleDefDoc);
        return {
            id: savedRoleDefDoc.id,
            definition,
        };
    }
    async getRoleDefinition(id) {
        const doc = await this.api.get(id);
        if (!doc || doc.type !== 'document') {
            return undefined;
        }
        // Check if the document has been soft-deleted
        // Soft-deleted documents have a deletedAt timestamp in their data
        const docAny = doc;
        if (docAny.deletedAt !== undefined && docAny.deletedAt !== null) {
            return undefined;
        }
        // Try to extract from metadata first (faster)
        const metaDef = doc.metadata?.[ROLE_DEF_META_KEY];
        if (metaDef && isAgentRoleDefinition(metaDef)) {
            return {
                id: doc.id,
                definition: metaDef,
            };
        }
        // Fall back to parsing the content
        if (doc.contentType === ROLE_DEF_CONTENT_TYPE) {
            try {
                const parsed = JSON.parse(doc.content);
                if (isAgentRoleDefinition(parsed)) {
                    return {
                        id: doc.id,
                        definition: parsed,
                    };
                }
            }
            catch {
                // Content is not valid JSON, ignore
            }
        }
        return undefined;
    }
    async getSystemPrompt(id) {
        const stored = await this.getRoleDefinition(id);
        if (!stored) {
            return undefined;
        }
        return this.getSystemPromptFromRef(stored.definition.systemPromptRef);
    }
    async getSystemPromptFromRef(documentId) {
        const doc = await this.api.get(documentId);
        if (!doc || doc.type !== 'document') {
            return undefined;
        }
        return doc.content;
    }
    async updateRoleDefinition(id, updates) {
        const existing = await this.getRoleDefinition(id);
        if (!existing) {
            throw new Error(`Role definition not found: ${id}`);
        }
        const now = createTimestamp();
        let newSystemPromptRef = existing.definition.systemPromptRef;
        // If system prompt is being updated, create a new version
        if (updates.systemPrompt !== undefined) {
            const currentPromptDoc = await this.api.get(existing.definition.systemPromptRef);
            if (!currentPromptDoc) {
                throw new Error(`System prompt document not found: ${existing.definition.systemPromptRef}`);
            }
            // Create new version of the system prompt document
            const updatedPromptDoc = await this.api.update(existing.definition.systemPromptRef, { content: updates.systemPrompt });
            newSystemPromptRef = updatedPromptDoc.id;
        }
        // Determine maxConcurrentTasks
        const newMaxConcurrentTasks = updates.maxConcurrentTasks ?? existing.definition.maxConcurrentTasks ?? 1;
        // Merge behaviors
        const newBehaviors = updates.behaviors || existing.definition.behaviors
            ? {
                ...existing.definition.behaviors,
                ...updates.behaviors,
            }
            : undefined;
        // Build updated definition
        const updatedDefinition = {
            ...existing.definition,
            name: updates.name ?? existing.definition.name,
            description: updates.description ?? existing.definition.description,
            systemPromptRef: newSystemPromptRef,
            maxConcurrentTasks: newMaxConcurrentTasks,
            behaviors: newBehaviors,
            tags: updates.tags ?? existing.definition.tags,
            updatedAt: now,
        };
        // Update the role definition document
        await this.api.update(id, {
            content: JSON.stringify(updatedDefinition, null, 2),
            metadata: {
                [ROLE_DEF_META_KEY]: updatedDefinition,
                systemPromptDocId: newSystemPromptRef,
            },
        });
        return {
            id,
            definition: updatedDefinition,
        };
    }
    async listRoleDefinitions(filter) {
        // Get all documents with the role-definition tag
        const docs = await this.api.list({ type: 'document' });
        // Filter to role definition documents
        const roleDefDocs = docs.filter((doc) => doc.tags.includes(ROLE_DEFINITION_TAGS.ROLE_DEFINITION));
        // Extract role definitions
        const results = [];
        for (const doc of roleDefDocs) {
            const stored = await this.getRoleDefinition(doc.id);
            if (stored) {
                results.push(stored);
            }
        }
        // Apply filters
        let filtered = results;
        if (filter) {
            if (filter.role !== undefined) {
                filtered = filtered.filter((r) => r.definition.role === filter.role);
            }
            if (filter.workerMode !== undefined) {
                filtered = filtered.filter((r) => {
                    if (r.definition.role !== 'worker')
                        return false;
                    const workerDef = r.definition;
                    return workerDef.workerMode === filter.workerMode;
                });
            }
            if (filter.stewardFocus !== undefined) {
                filtered = filtered.filter((r) => {
                    if (r.definition.role !== 'steward')
                        return false;
                    const stewardDef = r.definition;
                    return stewardDef.stewardFocus === filter.stewardFocus;
                });
            }
            if (filter.tags && filter.tags.length > 0) {
                filtered = filtered.filter((r) => {
                    const defTags = r.definition.tags ?? [];
                    return filter.tags.every((tag) => defTags.includes(tag));
                });
            }
            if (filter.nameContains !== undefined) {
                const searchTerm = filter.nameContains.toLowerCase();
                filtered = filtered.filter((r) => r.definition.name.toLowerCase().includes(searchTerm));
            }
        }
        return filtered;
    }
    async getRoleDefinitionsByRole(role) {
        return this.listRoleDefinitions({ role });
    }
    async getDefaultRoleDefinition(role) {
        const definitions = await this.getRoleDefinitionsByRole(role);
        return definitions[0];
    }
    async deleteRoleDefinition(id) {
        const existing = await this.getRoleDefinition(id);
        if (!existing) {
            return false;
        }
        // Delete the role definition document
        await this.api.delete(id);
        // Note: We don't delete the system prompt document as it may be
        // referenced by other role definitions or historical records
        return true;
    }
}
// ============================================================================
// Factory Function
// ============================================================================
/**
 * Creates a RoleDefinitionService instance
 */
export function createRoleDefinitionService(api) {
    return new RoleDefinitionServiceImpl(api);
}
//# sourceMappingURL=role-definition-service.js.map