Source: zpt/transform/PromptFormatter.js

/**
 * Formats content for optimal LLM consumption with structured prompts
 */
export default class PromptFormatter {
    constructor(options = {}) {
        this.config = {
            defaultFormat: options.defaultFormat || 'structured',
            includeMetadata: options.includeMetadata !== false,
            includeInstructions: options.includeInstructions !== false,
            preserveStructure: options.preserveStructure !== false,
            contextMarkers: options.contextMarkers !== false,
            debugMode: options.debugMode || false,
            ...options
        };

        this.initializeFormats();
        this.initializeTemplates();
        this.initializeInstructions();
    }

    /**
     * Initialize available output formats
     */
    initializeFormats() {
        this.formats = {
            json: {
                name: 'JSON Format',
                handler: this.formatAsJSON.bind(this),
                description: 'Structured JSON output for programmatic consumption',
                useCases: ['API responses', 'data processing', 'structured analysis']
            },
            markdown: {
                name: 'Markdown Format',
                handler: this.formatAsMarkdown.bind(this),
                description: 'Human-readable markdown with structure preservation',
                useCases: ['documentation', 'reports', 'readable output']
            },
            structured: {
                name: 'Structured Prompt Format',
                handler: this.formatAsStructured.bind(this),
                description: 'LLM-optimized format with clear sections and context',
                useCases: ['LLM prompts', 'conversation', 'reasoning tasks']
            },
            conversational: {
                name: 'Conversational Format',
                handler: this.formatAsConversational.bind(this),
                description: 'Natural language format for chat interfaces',
                useCases: ['chat responses', 'summaries', 'explanations']
            },
            analytical: {
                name: 'Analytical Format',
                handler: this.formatAsAnalytical.bind(this),
                description: 'Detailed analysis format with insights and patterns',
                useCases: ['research', 'analysis', 'insights generation']
            }
        };
    }

    /**
     * Initialize formatting templates
     */
    initializeTemplates() {
        this.templates = {
            structured: {
                header: '# ZPT Navigation Results\n\n',
                navigation: '## Navigation Context\n**Zoom:** {zoom}\n**Pan:** {pan}\n**Tilt:** {tilt}\n\n',
                content: '## Content\n\n{content}\n\n',
                metadata: '## Metadata\n{metadata}\n\n',
                footer: '---\n*Generated by ZPT Navigation System*'
            },
            analytical: {
                header: '# Analysis Report\n\n',
                summary: '## Executive Summary\n{summary}\n\n',
                findings: '## Key Findings\n{findings}\n\n',
                details: '## Detailed Analysis\n{details}\n\n',
                patterns: '## Patterns & Insights\n{patterns}\n\n',
                metadata: '## Analysis Metadata\n{metadata}\n\n'
            },
            conversational: {
                greeting: 'Based on your navigation through the corpus using zoom level "{zoom}", here\'s what I found:\n\n',
                content: '{content}\n\n',
                context: 'This analysis was generated using {tilt} representation{filters}.\n\n',
                closing: 'Would you like to explore further or adjust the navigation parameters?'
            }
        };
    }

    /**
     * Initialize instruction sets for different use cases
     */
    initializeInstructions() {
        this.instructions = {
            analysis: {
                prefix: 'Please analyze the following content extracted from a knowledge corpus:',
                context: 'The content was selected using specific navigation parameters (zoom/pan/tilt) to focus on relevant information.',
                guidance: 'Pay attention to patterns, relationships, and key insights. Consider the navigation context when interpreting the results.',
                suffix: 'Provide a comprehensive analysis considering both the content and the navigation methodology used.'
            },
            summarization: {
                prefix: 'Please summarize the following corpus content:',
                context: 'This content represents a focused view of a larger knowledge corpus, filtered by specific criteria.',
                guidance: 'Create a concise summary that captures the essential information while maintaining context.',
                suffix: 'Focus on the most important points and their relationships.'
            },
            question_answering: {
                prefix: 'Use the following corpus content to answer questions:',
                context: 'The content has been specifically selected and filtered to be relevant to potential queries.',
                guidance: 'Base your answers strictly on the provided content. If information is not available, indicate this clearly.',
                suffix: 'Provide accurate, evidence-based responses citing the relevant sections.'
            },
            exploration: {
                prefix: 'Explore and explain the following content from a knowledge corpus:',
                context: 'This content represents a specific perspective through the corpus based on navigation parameters.',
                guidance: 'Identify interesting patterns, connections, and insights. Consider multiple viewpoints.',
                suffix: 'Highlight discoveries and suggest areas for further exploration.'
            }
        };
    }

    /**
     * Main formatting method - transforms projected content for LLM consumption
     * @param {Object} projectedContent - Content from TiltProjector
     * @param {Object} navigationContext - ZPT navigation context
     * @param {Object} options - Formatting options
     * @returns {Object} Formatted content ready for LLM
     */
    async format(projectedContent, navigationContext, options = {}) {
        const startTime = Date.now();
        const opts = { ...this.config, ...options };

        try {
            // Determine output format
            const format = opts.format || this.config.defaultFormat;
            const formatter = this.formats[format];

            if (!formatter) {
                throw new Error(`Unknown format: ${format}`);
            }

            // Prepare formatting context
            const formattingContext = this.buildFormattingContext(
                projectedContent, 
                navigationContext, 
                opts
            );

            // Apply format-specific transformation
            const formattedContent = await formatter.handler(formattingContext, opts);

            // Add instructions if requested
            const instructionalContent = this.addInstructions(formattedContent, opts);

            // Add metadata markers if requested
            const finalContent = this.addContextMarkers(instructionalContent, formattingContext, opts);

            const result = {
                content: finalContent,
                format,
                metadata: {
                    originalProjection: projectedContent.representation,
                    outputFormat: format,
                    hasInstructions: opts.includeInstructions,
                    hasMetadata: opts.includeMetadata,
                    processingTime: Date.now() - startTime,
                    tokenEstimate: this.estimateTokenCount(finalContent)
                },
                context: formattingContext
            };

            return result;

        } catch (error) {
            throw new Error(`Formatting failed: ${error.message}`);
        }
    }

    /**
     * Build comprehensive formatting context
     */
    buildFormattingContext(projectedContent, navigationContext, options) {
        const { representation, data, metadata } = projectedContent;
        const { zoom, pan, tilt } = navigationContext;

        return {
            // Core content
            projection: {
                type: representation,
                data,
                metadata
            },
            
            // Navigation context
            navigation: {
                zoom,
                pan,
                tilt,
                hasFilters: Object.keys(pan || {}).length > 0,
                filterSummary: this.summarizeFilters(pan)
            },

            // Content analysis
            analysis: {
                contentType: this.analyzeContentType(data),
                complexity: this.assessComplexity(data),
                structure: this.analyzeStructure(data),
                insights: this.extractInsights(data, representation)
            },

            // Formatting context
            formatting: {
                timestamp: new Date().toISOString(),
                options,
                purpose: options.purpose || 'general'
            }
        };
    }

    /**
     * Format as JSON
     */
    async formatAsJSON(context, options) {
        const { projection, navigation, analysis } = context;

        const jsonOutput = {
            zpt_navigation: {
                zoom: navigation.zoom,
                pan: navigation.pan,
                tilt: navigation.tilt
            },
            content: {
                type: projection.type,
                data: projection.data,
                analysis: options.includeAnalysis ? analysis : undefined
            },
            metadata: options.includeMetadata ? {
                projection_metadata: projection.metadata,
                content_analysis: analysis,
                formatting: context.formatting
            } : undefined
        };

        // Clean undefined values
        return JSON.stringify(jsonOutput, (key, value) => value === undefined ? null : value, 2);
    }

    /**
     * Format as Markdown
     */
    async formatAsMarkdown(context, options) {
        const { projection, navigation, analysis } = context;
        let markdown = '';

        // Header
        markdown += `# Corpus Navigation Results\n\n`;

        // Navigation context
        markdown += `## Navigation Parameters\n\n`;
        markdown += `- **Zoom Level:** ${navigation.zoom}\n`;
        markdown += `- **Tilt Representation:** ${navigation.tilt}\n`;
        
        if (navigation.hasFilters) {
            markdown += `- **Applied Filters:** ${navigation.filterSummary}\n`;
        }
        markdown += `\n`;

        // Content section
        markdown += `## Content\n\n`;
        markdown += this.formatContentAsMarkdown(projection.data, projection.type);

        // Analysis section
        if (options.includeAnalysis && analysis) {
            markdown += `\n## Analysis\n\n`;
            markdown += this.formatAnalysisAsMarkdown(analysis);
        }

        // Metadata section
        if (options.includeMetadata) {
            markdown += `\n## Metadata\n\n`;
            markdown += this.formatMetadataAsMarkdown(projection.metadata, context.formatting);
        }

        return markdown;
    }

    /**
     * Format as structured prompt
     */
    async formatAsStructured(context, options) {
        const { projection, navigation, analysis } = context;
        const template = this.templates.structured;

        let structured = '';

        // Header
        structured += template.header;

        // Navigation context
        const panDescription = navigation.hasFilters ? 
            ` with filters: ${navigation.filterSummary}` : '';
        
        structured += template.navigation
            .replace('{zoom}', navigation.zoom)
            .replace('{pan}', panDescription)
            .replace('{tilt}', navigation.tilt);

        // Content
        const formattedContent = this.formatContentForLLM(projection.data, projection.type, options);
        structured += template.content.replace('{content}', formattedContent);

        // Metadata
        if (options.includeMetadata) {
            const metadataText = this.formatMetadataForLLM(projection.metadata, analysis);
            structured += template.metadata.replace('{metadata}', metadataText);
        }

        // Footer
        structured += template.footer;

        return structured;
    }

    /**
     * Format as conversational
     */
    async formatAsConversational(context, options) {
        const { projection, navigation, analysis } = context;
        const template = this.templates.conversational;

        let conversational = '';

        // Greeting with context
        conversational += template.greeting.replace('{zoom}', navigation.zoom);

        // Content in natural language
        const naturalContent = this.formatContentNaturally(projection.data, projection.type);
        conversational += template.content.replace('{content}', naturalContent);

        // Context explanation
        const filterText = navigation.hasFilters ? 
            ` and filtered by ${navigation.filterSummary}` : '';
        
        conversational += template.context
            .replace('{tilt}', navigation.tilt)
            .replace('{filters}', filterText);

        // Closing
        conversational += template.closing;

        return conversational;
    }

    /**
     * Format as analytical
     */
    async formatAsAnalytical(context, options) {
        const { projection, navigation, analysis } = context;
        const template = this.templates.analytical;

        let analytical = '';

        // Header
        analytical += template.header;

        // Executive summary
        const summary = this.generateExecutiveSummary(projection.data, navigation, analysis);
        analytical += template.summary.replace('{summary}', summary);

        // Key findings
        const findings = this.extractKeyFindings(projection.data, projection.type, analysis);
        analytical += template.findings.replace('{findings}', findings);

        // Detailed analysis
        const details = this.formatDetailedAnalysis(projection.data, projection.type);
        analytical += template.details.replace('{details}', details);

        // Patterns and insights
        const patterns = this.identifyPatterns(projection.data, analysis);
        analytical += template.patterns.replace('{patterns}', patterns);

        // Metadata
        if (options.includeMetadata) {
            const metadata = this.formatAnalyticalMetadata(projection.metadata, context.formatting);
            analytical += template.metadata.replace('{metadata}', metadata);
        }

        return analytical;
    }

    /**
     * Content formatting helpers
     */
    formatContentAsMarkdown(data, type) {
        switch (type) {
            case 'vector':
                return this.formatEmbeddingsAsMarkdown(data);
            case 'text':
                return this.formatKeywordsAsMarkdown(data);
            case 'structured':
                return this.formatGraphAsMarkdown(data);
            case 'sequence':
                return this.formatTemporalAsMarkdown(data);
            default:
                return `\`\`\`json\n${JSON.stringify(data, null, 2)}\n\`\`\``;
        }
    }

    formatEmbeddingsAsMarkdown(data) {
        const { embeddings, aggregateStats, centroid } = data;
        
        let markdown = `### Embedding Analysis\n\n`;
        markdown += `- **Total embeddings:** ${embeddings.length}\n`;
        markdown += `- **Average similarity:** ${aggregateStats.avgSimilarity.toFixed(3)}\n`;
        markdown += `- **Dimension:** ${aggregateStats.dimension}\n`;
        markdown += `- **Model:** ${aggregateStats.model}\n\n`;

        if (embeddings.length > 0) {
            markdown += `#### Top Similar Items\n\n`;
            const topItems = embeddings
                .sort((a, b) => b.similarity - a.similarity)
                .slice(0, 5);

            topItems.forEach((item, index) => {
                markdown += `${index + 1}. **Similarity:** ${item.similarity.toFixed(3)} - ${item.uri}\n`;
            });
        }

        return markdown;
    }

    formatKeywordsAsMarkdown(data) {
        const { globalKeywords, summary, stats } = data;
        
        let markdown = `### Keyword Analysis\n\n`;
        markdown += `**Summary:** ${summary}\n\n`;
        markdown += `- **Total unique keywords:** ${stats.totalKeywords}\n`;
        markdown += `- **Average keywords per item:** ${stats.avgKeywordsPerCorpuscle.toFixed(1)}\n`;
        markdown += `- **Coverage score:** ${stats.coverageScore.toFixed(3)}\n\n`;

        if (globalKeywords.length > 0) {
            markdown += `#### Top Keywords\n\n`;
            globalKeywords.slice(0, 10).forEach((kw, index) => {
                markdown += `${index + 1}. **${kw.keyword}** (score: ${kw.score.toFixed(3)}, frequency: ${kw.frequency})\n`;
            });
        }

        return markdown;
    }

    formatGraphAsMarkdown(data) {
        const { nodes, edges, communities, metrics } = data;
        
        let markdown = `### Graph Analysis\n\n`;
        markdown += `- **Nodes:** ${metrics.nodeCount}\n`;
        markdown += `- **Edges:** ${metrics.edgeCount}\n`;
        markdown += `- **Density:** ${metrics.density.toFixed(3)}\n`;
        markdown += `- **Average degree:** ${metrics.avgDegree.toFixed(1)}\n`;
        markdown += `- **Communities:** ${communities.length}\n\n`;

        if (communities.length > 0) {
            markdown += `#### Communities\n\n`;
            communities.forEach((community, index) => {
                markdown += `${index + 1}. **${community.id}** (${community.size} members)\n`;
            });
        }

        return markdown;
    }

    formatTemporalAsMarkdown(data) {
        const { events, timeline, stats } = data;
        
        let markdown = `### Temporal Analysis\n\n`;
        markdown += `- **Total events:** ${stats.eventCount}\n`;
        markdown += `- **Timeline span:** ${stats.timelineSpan} periods\n`;
        markdown += `- **Duration:** ${Math.round(stats.duration / (24 * 60 * 60 * 1000))} days\n`;
        markdown += `- **Event frequency:** ${stats.frequency.toFixed(2)} events/day\n\n`;

        if (timeline.length > 0) {
            markdown += `#### Timeline\n\n`;
            timeline.slice(0, 10).forEach(period => {
                markdown += `- **${period.period}**: ${period.count} events (avg score: ${period.avgScore.toFixed(2)})\n`;
            });
        }

        return markdown;
    }

    formatContentForLLM(data, type, options) {
        switch (type) {
            case 'vector':
                return this.formatEmbeddingsForLLM(data);
            case 'text':
                return this.formatKeywordsForLLM(data);
            case 'structured':
                return this.formatGraphForLLM(data);
            case 'sequence':
                return this.formatTemporalForLLM(data);
            default:
                return JSON.stringify(data, null, 2);
        }
    }

    formatEmbeddingsForLLM(data) {
        const { embeddings, aggregateStats } = data;
        
        let content = `EMBEDDING ANALYSIS RESULTS:\n\n`;
        content += `Model: ${aggregateStats.model}\n`;
        content += `Total items: ${embeddings.length}\n`;
        content += `Average similarity: ${aggregateStats.avgSimilarity.toFixed(3)}\n\n`;

        if (embeddings.length > 0) {
            content += `TOP SIMILAR ITEMS:\n`;
            embeddings
                .sort((a, b) => b.similarity - a.similarity)
                .slice(0, 10)
                .forEach((item, index) => {
                    content += `${index + 1}. [${item.similarity.toFixed(3)}] ${item.uri}\n`;
                });
        }

        return content;
    }

    formatKeywordsForLLM(data) {
        const { globalKeywords, summary, corpuscleKeywords } = data;
        
        let content = `KEYWORD ANALYSIS RESULTS:\n\n`;
        content += `Summary: ${summary}\n\n`;

        content += `KEY TERMS:\n`;
        globalKeywords.slice(0, 15).forEach((kw, index) => {
            content += `${index + 1}. ${kw.keyword} (${kw.score.toFixed(3)})\n`;
        });

        if (corpuscleKeywords.length > 0) {
            content += `\nCONTENT EXCERPTS:\n`;
            corpuscleKeywords.slice(0, 5).forEach((item, index) => {
                const topKeywords = item.keywords.slice(0, 3).map(k => k.keyword).join(', ');
                content += `${index + 1}. Keywords: ${topKeywords}\n   Content: ${item.content}\n\n`;
            });
        }

        return content;
    }

    formatGraphForLLM(data) {
        const { nodes, edges, communities, metrics } = data;
        
        let content = `GRAPH ANALYSIS RESULTS:\n\n`;
        content += `Network structure: ${nodes.length} nodes, ${edges.length} edges\n`;
        content += `Density: ${metrics.density.toFixed(3)}\n`;
        content += `Communities: ${communities.length}\n\n`;

        // Top nodes by score
        const topNodes = nodes
            .sort((a, b) => (b.score || 0) - (a.score || 0))
            .slice(0, 10);

        content += `TOP ENTITIES:\n`;
        topNodes.forEach((node, index) => {
            content += `${index + 1}. ${node.label} (${node.type}, score: ${(node.score || 0).toFixed(3)})\n`;
        });

        if (communities.length > 0) {
            content += `\nCOMMUNITIES:\n`;
            communities.slice(0, 5).forEach((community, index) => {
                content += `${index + 1}. ${community.id}: ${community.size} members\n`;
            });
        }

        return content;
    }

    formatTemporalForLLM(data) {
        const { events, timeline, sequences, stats } = data;
        
        let content = `TEMPORAL ANALYSIS RESULTS:\n\n`;
        content += `Time range: ${stats.duration / (24 * 60 * 60 * 1000)} days\n`;
        content += `Total events: ${events.length}\n`;
        content += `Event frequency: ${stats.frequency.toFixed(2)} events/day\n\n`;

        content += `TIMELINE:\n`;
        timeline.slice(0, 10).forEach(period => {
            content += `${period.period}: ${period.count} events\n`;
        });

        if (sequences.length > 0) {
            content += `\nEVENT SEQUENCES:\n`;
            sequences.slice(0, 3).forEach((seq, index) => {
                content += `${index + 1}. ${seq.events.length} events over ${Math.round(seq.duration / (24 * 60 * 60 * 1000))} days\n`;
            });
        }

        return content;
    }

    /**
     * Content naturally formatted for conversation
     */
    formatContentNaturally(data, type) {
        switch (type) {
            case 'vector':
                return this.formatEmbeddingsNaturally(data);
            case 'text':
                return this.formatKeywordsNaturally(data);
            case 'structured':
                return this.formatGraphNaturally(data);
            case 'sequence':
                return this.formatTemporalNaturally(data);
            default:
                return 'I found some data, but it\'s in a format I can\'t easily describe.';
        }
    }

    formatEmbeddingsNaturally(data) {
        const { embeddings, aggregateStats } = data;
        
        let natural = `I analyzed ${embeddings.length} items using semantic embeddings. `;
        
        if (aggregateStats.avgSimilarity > 0.7) {
            natural += `The content shows high semantic similarity (average ${aggregateStats.avgSimilarity.toFixed(2)}), `;
            natural += `suggesting these items are closely related in meaning.`;
        } else if (aggregateStats.avgSimilarity > 0.3) {
            natural += `The content shows moderate semantic relationships, with some related themes emerging.`;
        } else {
            natural += `The content is quite diverse, covering different topics and concepts.`;
        }

        return natural;
    }

    formatKeywordsNaturally(data) {
        const { globalKeywords, summary } = data;
        
        let natural = summary;
        
        if (globalKeywords.length > 5) {
            const topTerms = globalKeywords.slice(0, 5).map(k => k.keyword).join(', ');
            natural += ` The most prominent terms are: ${topTerms}.`;
        }

        return natural;
    }

    formatGraphNaturally(data) {
        const { nodes, communities, metrics } = data;
        
        let natural = `I found a network of ${nodes.length} connected entities. `;
        
        if (communities.length > 1) {
            natural += `The network naturally groups into ${communities.length} communities, `;
            natural += `suggesting distinct but related topic clusters.`;
        } else {
            natural += `The entities form a cohesive network with strong interconnections.`;
        }

        if (metrics.density > 0.1) {
            natural += ` The network is well-connected with many relationships between entities.`;
        }

        return natural;
    }

    formatTemporalNaturally(data) {
        const { events, stats } = data;
        
        let natural = `I analyzed ${events.length} events spanning ${Math.round(stats.duration / (24 * 60 * 60 * 1000))} days. `;
        
        if (stats.frequency > 1) {
            natural += `The activity level is quite high, with about ${stats.frequency.toFixed(1)} events per day.`;
        } else if (stats.frequency > 0.1) {
            natural += `The activity is moderate, with events occurring regularly over time.`;
        } else {
            natural += `The events are spread out over a longer time period.`;
        }

        return natural;
    }

    /**
     * Analysis and insight extraction
     */
    analyzeContentType(data) {
        if (data.embeddings) return 'semantic_embeddings';
        if (data.globalKeywords) return 'keyword_extraction';
        if (data.nodes && data.edges) return 'graph_structure';
        if (data.events && data.timeline) return 'temporal_sequence';
        return 'unknown';
    }

    assessComplexity(data) {
        let complexity = 0;
        
        if (data.embeddings) complexity += data.embeddings.length / 100;
        if (data.globalKeywords) complexity += data.globalKeywords.length / 50;
        if (data.nodes) complexity += data.nodes.length / 200;
        if (data.events) complexity += data.events.length / 500;
        
        return Math.min(1.0, complexity);
    }

    analyzeStructure(data) {
        const structure = {
            hierarchical: false,
            networked: false,
            sequential: false,
            categorical: false
        };

        if (data.nodes && data.edges) structure.networked = true;
        if (data.events && data.timeline) structure.sequential = true;
        if (data.communities) structure.hierarchical = true;
        if (data.globalKeywords) structure.categorical = true;

        return structure;
    }

    extractInsights(data, representation) {
        const insights = [];

        switch (representation) {
            case 'embedding':
                if (data.aggregateStats?.avgSimilarity > 0.8) {
                    insights.push('High semantic coherence detected');
                }
                break;
            case 'keywords':
                if (data.stats?.coverageScore > 0.7) {
                    insights.push('Strong keyword coverage across content');
                }
                break;
            case 'graph':
                if (data.metrics?.density > 0.1) {
                    insights.push('Well-connected entity network');
                }
                break;
            case 'temporal':
                if (data.patterns?.length > 0) {
                    insights.push('Temporal patterns detected');
                }
                break;
        }

        return insights;
    }

    /**
     * Helper methods for specific formatting tasks
     */
    summarizeFilters(pan) {
        if (!pan || Object.keys(pan).length === 0) return 'none';
        
        const filters = [];
        if (pan.topic) filters.push(`topic: ${pan.topic.value}`);
        if (pan.entity) filters.push(`entities: ${pan.entity.count}`);
        if (pan.temporal) filters.push('temporal constraints');
        if (pan.geographic) filters.push('geographic bounds');
        
        return filters.join(', ');
    }

    generateExecutiveSummary(data, navigation, analysis) {
        let summary = `Analysis of corpus content using ${navigation.zoom} zoom level with ${navigation.tilt} representation. `;
        
        if (analysis.insights.length > 0) {
            summary += `Key insights: ${analysis.insights.join(', ')}. `;
        }
        
        summary += `Content complexity: ${(analysis.complexity * 100).toFixed(0)}%.`;
        
        return summary;
    }

    extractKeyFindings(data, type, analysis) {
        const findings = [];
        
        switch (type) {
            case 'vector':
                if (data.aggregateStats) {
                    findings.push(`Semantic similarity: ${data.aggregateStats.avgSimilarity.toFixed(3)}`);
                    findings.push(`Content items analyzed: ${data.embeddings.length}`);
                }
                break;
            case 'text':
                if (data.stats) {
                    findings.push(`Unique keywords identified: ${data.stats.totalKeywords}`);
                    findings.push(`Keyword coverage: ${(data.stats.coverageScore * 100).toFixed(1)}%`);
                }
                break;
            case 'structured':
                if (data.metrics) {
                    findings.push(`Network density: ${data.metrics.density.toFixed(3)}`);
                    findings.push(`Communities detected: ${data.communities?.length || 0}`);
                }
                break;
            case 'sequence':
                if (data.stats) {
                    findings.push(`Event frequency: ${data.stats.frequency.toFixed(2)} events/day`);
                    findings.push(`Temporal sequences: ${data.sequences?.length || 0}`);
                }
                break;
        }
        
        return findings.map((finding, index) => `${index + 1}. ${finding}`).join('\n');
    }

    formatDetailedAnalysis(data, type) {
        // Detailed analysis would go here - simplified for brevity
        return `Detailed analysis of ${type} data with ${JSON.stringify(data).length} characters of raw data.`;
    }

    identifyPatterns(data, analysis) {
        const patterns = [];
        
        if (analysis.structure.networked) {
            patterns.push('Network connectivity patterns identified');
        }
        
        if (analysis.structure.sequential) {
            patterns.push('Temporal progression patterns observed');
        }
        
        if (analysis.complexity > 0.7) {
            patterns.push('High complexity suggests rich interconnections');
        }
        
        return patterns.length > 0 ? patterns.map((p, i) => `${i + 1}. ${p}`).join('\n') : 'No significant patterns detected.';
    }

    /**
     * Instruction and context enhancement
     */
    addInstructions(content, options) {
        if (!options.includeInstructions) return content;
        
        const instructionSet = options.instructionSet || 'analysis';
        const instructions = this.instructions[instructionSet];
        
        if (!instructions) return content;
        
        let instructionalContent = `${instructions.prefix}\n\n`;
        instructionalContent += `${instructions.context}\n\n`;
        instructionalContent += `${instructions.guidance}\n\n`;
        instructionalContent += `---\n\n${content}\n\n---\n\n`;
        instructionalContent += `${instructions.suffix}`;
        
        return instructionalContent;
    }

    addContextMarkers(content, context, options) {
        if (!options.contextMarkers) return content;
        
        const markers = {
            start: `<!-- ZPT_START: ${context.navigation.zoom}/${context.navigation.tilt} -->`,
            end: `<!-- ZPT_END: ${new Date().toISOString()} -->`,
            metadata: `<!-- ZPT_META: ${JSON.stringify(context.navigation)} -->`
        };
        
        return `${markers.start}\n${markers.metadata}\n\n${content}\n\n${markers.end}`;
    }

    /**
     * Metadata formatting
     */
    formatMetadataAsMarkdown(metadata, formatting) {
        let md = '```yaml\n';
        md += `timestamp: ${formatting.timestamp}\n`;
        md += `projection_type: ${metadata.projection?.type || 'unknown'}\n`;
        md += `processing_time: ${metadata.processingTime || 0}ms\n`;
        md += '```';
        return md;
    }

    formatMetadataForLLM(metadata, analysis) {
        let meta = `Processing Details:\n`;
        meta += `- Timestamp: ${new Date().toISOString()}\n`;
        meta += `- Processing time: ${metadata.processingTime || 0}ms\n`;
        if (analysis) {
            meta += `- Content complexity: ${(analysis.complexity * 100).toFixed(0)}%\n`;
        }
        return meta;
    }

    formatAnalyticalMetadata(metadata, formatting) {
        return this.formatMetadataAsMarkdown(metadata, formatting);
    }

    /**
     * Utility methods
     */
    estimateTokenCount(content) {
        // Simple token estimation - 4 characters per token average
        return Math.ceil(content.length / 4);
    }

    /**
     * Get available formats
     */
    getAvailableFormats() {
        return Object.keys(this.formats);
    }

    /**
     * Get format information
     */
    getFormatInfo(formatName) {
        return this.formats[formatName] ? { ...this.formats[formatName] } : null;
    }

    /**
     * Get available instruction sets
     */
    getAvailableInstructions() {
        return Object.keys(this.instructions);
    }

    /**
     * Get instruction set information
     */
    getInstructionInfo(instructionSet) {
        return this.instructions[instructionSet] ? { ...this.instructions[instructionSet] } : null;
    }

    /**
     * Validate formatting options
     */
    validateOptions(options) {
        const issues = [];
        
        if (options.format && !this.formats[options.format]) {
            issues.push(`Unknown format: ${options.format}`);
        }
        
        if (options.instructionSet && !this.instructions[options.instructionSet]) {
            issues.push(`Unknown instruction set: ${options.instructionSet}`);
        }
        
        return {
            valid: issues.length === 0,
            issues
        };
    }
}