import * as fs from '../../utils/fs-native.js';
import path from 'path';
import { maskCredentials } from '../../utils/credential-masker.js';
/**
 * PromptLogger - Automatic logging of user prompts to increment logs
 *
 * Features:
 * - Logs every user prompt to appropriate increment's logs/ folder
 * - Organized by day (YYYY-MM-DD)
 * - **SECURITY**: Automatically masks credentials before saving
 * - Copies attachments to assets/ subfolder
 * - Smart increment detection (active increments)
 * - Fallback to orphaned logs if no active increment
 */
export class PromptLogger {
    constructor(workingDir) {
        this.workingDir = workingDir;
    }
    /**
     * Log a user prompt to the daily session file
     *
     * @param promptText - Exact user prompt text
     * @param attachments - Optional attachments (images, files)
     */
    async logPrompt(promptText, attachments = []) {
        // Find appropriate increment for logging
        const incrementId = await this.findIncrementForLogging();
        // Determine log directory
        const logDir = incrementId
            ? path.join(this.workingDir, '.specweave/increments', incrementId, 'logs')
            : path.join(this.workingDir, '.specweave/logs/orphaned');
        // Get current date for daily organization
        const now = new Date();
        const dateStr = now.toISOString().slice(0, 10); // YYYY-MM-DD
        const dailyDir = path.join(logDir, dateStr);
        const assetsDir = path.join(dailyDir, 'assets');
        // Ensure directories exist
        await fs.ensureDir(assetsDir);
        // Session file path
        const sessionFile = path.join(dailyDir, 'session.md');
        // Create session file header if new file
        if (!await fs.pathExists(sessionFile)) {
            const header = this.createSessionHeader(dateStr, incrementId);
            await fs.writeFile(sessionFile, header);
        }
        // Build prompt entry
        const time = now.toTimeString().slice(0, 8); // HH:MM:SS
        const entry = this.buildPromptEntry(time, promptText, attachments);
        // Append to session file (atomic operation)
        await fs.appendFile(sessionFile, entry);
        // Copy attachments to assets/
        if (attachments.length > 0) {
            await this.copyAttachments(attachments, assetsDir);
        }
        // Create/update README.md in logs/ folder
        await this.ensureLogsReadme(path.dirname(dailyDir));
    }
    /**
     * Create session file header
     */
    createSessionHeader(date, incrementId) {
        const location = incrementId
            ? `Increment: ${incrementId}`
            : 'Location: Orphaned logs (no active increment)';
        return `# Session Log - ${date}

Generated by SpecWeave automatic prompt logging.
${location}

---

`;
    }
    /**
     * Build a single prompt entry
     *
     * SECURITY: Masks all credentials before writing to log file
     */
    buildPromptEntry(time, promptText, attachments) {
        // Mask credentials in prompt text before logging
        const sanitizedPrompt = maskCredentials(promptText);
        let entry = `## ${time} - User Prompt\n\n`;
        entry += `${sanitizedPrompt}\n\n`;
        if (attachments.length > 0) {
            entry += `**Attachments**:\n`;
            attachments.forEach((att, idx) => {
                const assetFilename = this.getAssetFilename(att, idx + 1);
                entry += `- \`assets/${assetFilename}\` - ${att.name}\n`;
            });
        }
        else {
            entry += `**Attachments**: None\n`;
        }
        entry += `\n---\n\n`;
        return entry;
    }
    /**
     * Copy attachments to assets folder
     */
    async copyAttachments(attachments, assetsDir) {
        for (let i = 0; i < attachments.length; i++) {
            const att = attachments[i];
            const destFilename = this.getAssetFilename(att, i + 1);
            const destPath = path.join(assetsDir, destFilename);
            try {
                await fs.copy(att.path, destPath);
            }
            catch (error) {
                console.error(`Failed to copy attachment ${att.name}:`, error);
                // Continue with other attachments
            }
        }
    }
    /**
     * Generate numbered asset filename
     */
    getAssetFilename(att, index) {
        const ext = path.extname(att.name);
        const typePrefix = this.getTypePrefix(att.type);
        const paddedIndex = String(index).padStart(3, '0');
        return `${typePrefix}-${paddedIndex}${ext}`;
    }
    /**
     * Get prefix based on file type
     */
    getTypePrefix(type) {
        if (type.startsWith('image/'))
            return 'screenshot';
        if (type.startsWith('text/'))
            return 'text';
        if (type === 'application/pdf')
            return 'document';
        return 'file';
    }
    /**
     * Find the appropriate increment for logging
     *
     * Priority:
     * 1. Most recently modified active increment (if multiple active)
     * 2. Single active increment
     * 3. null (log to orphaned/)
     *
     * @returns Increment ID or null for orphaned logs
     */
    async findIncrementForLogging() {
        const incrementsDir = path.join(this.workingDir, '.specweave/increments');
        if (!await fs.pathExists(incrementsDir)) {
            return null;
        }
        // Find all active increments
        const activeIncrements = [];
        const dirs = await fs.readdir(incrementsDir);
        for (const dir of dirs) {
            const metadataPath = path.join(incrementsDir, dir, 'metadata.json');
            if (await fs.pathExists(metadataPath)) {
                try {
                    const metadata = await fs.readJson(metadataPath);
                    if (metadata.status === 'active') {
                        const lastActivity = new Date(metadata.lastActivity || metadata.created || Date.now());
                        activeIncrements.push({
                            id: dir,
                            lastActivity
                        });
                    }
                }
                catch (error) {
                    // Skip invalid metadata files
                    continue;
                }
            }
        }
        // No active increments → orphaned logs
        if (activeIncrements.length === 0) {
            return null;
        }
        // Single active → use it
        if (activeIncrements.length === 1) {
            return activeIncrements[0].id;
        }
        // Multiple active (max 2 allowed) → use most recent
        activeIncrements.sort((a, b) => b.lastActivity.getTime() - a.lastActivity.getTime());
        return activeIncrements[0].id;
    }
    /**
     * Ensure README.md exists in logs/ folder
     */
    async ensureLogsReadme(logsDir) {
        const readmePath = path.join(logsDir, 'README.md');
        // Only create if doesn't exist
        if (await fs.pathExists(readmePath)) {
            return;
        }
        const readme = this.createLogsReadme();
        await fs.writeFile(readmePath, readme);
    }
    /**
     * Create README.md content for logs/ folder
     */
    createLogsReadme() {
        const now = new Date().toISOString().replace('T', ' ').slice(0, 19);
        return `# Prompt Logs

This folder contains automatic logs of all user prompts for this increment.

## Structure

\`\`\`
logs/
├── 2025-11-13/
│   ├── session.md      # All prompts for this day
│   └── assets/         # Images, screenshots, files
├── 2025-11-14/
│   └── session.md
└── README.md           # This file
\`\`\`

## Purpose

- **Audit trail**: Review what was asked and when
- **Context preservation**: Understand past decisions
- **Debug tool**: Trace where certain implementations came from
- **Knowledge base**: Search past conversations

## Privacy Note

These logs contain YOUR prompts with automatic credential masking applied.

**Security Features**:
- Credentials (tokens, passwords, API keys) are automatically masked
- Format: Shows first 4 and last 4 characters (e.g., ghp_****def)
- Protects: GitHub tokens, JIRA credentials, database URLs, etc.

**What's still logged**:
- Code snippets (non-sensitive)
- Personal information (review before sharing)
- Project-specific details

**Recommendation**: Review logs before committing to public repositories.

## Configuration

To disable logging, edit .specweave/config.json:

{
  "logging": {
    "enabled": false
  }
}

## Generated by SpecWeave

Last updated: ${now}
`;
    }
}
//# sourceMappingURL=prompt-logger.js.map