import { promises as fs } from 'fs';
import path from 'path';
import { StorageManager } from '../../storage/storage-manager.js';
export class ADRStore {
    storageManager;
    recordsPath;
    templatesPath;
    initialized = false;
    constructor() {
        this.storageManager = new StorageManager();
    }
    async initialize() {
        if (this.initialized)
            return;
        const { data } = await this.storageManager.getStorageLocation();
        const adrBasePath = path.join(data, 'adr');
        this.recordsPath = path.join(adrBasePath, 'records');
        this.templatesPath = path.join(adrBasePath, 'templates');
        // Create directories if they don't exist
        await fs.mkdir(this.recordsPath, { recursive: true });
        await fs.mkdir(this.templatesPath, { recursive: true });
        this.initialized = true;
    }
    getADRFilename(adr) {
        const titleSlug = adr.title
            .toLowerCase()
            .replace(/[^a-z0-9]+/g, '-')
            .replace(/^-|-$/g, '');
        return `${adr.id}-${titleSlug}.json`;
    }
    async saveADR(adr) {
        await this.ensureInitialized();
        const filename = this.getADRFilename(adr);
        const filepath = path.join(this.recordsPath, filename);
        await fs.writeFile(filepath, JSON.stringify(adr, null, 2), 'utf-8');
    }
    async loadADR(id) {
        await this.ensureInitialized();
        try {
            // Find the file that starts with the ADR ID
            const files = await fs.readdir(this.recordsPath);
            const adrFile = files.find(f => f.startsWith(`${id}-`) && f.endsWith('.json'));
            if (!adrFile)
                return null;
            const filepath = path.join(this.recordsPath, adrFile);
            const content = await fs.readFile(filepath, 'utf-8');
            const adr = JSON.parse(content);
            // Convert date strings back to Date objects
            adr.date = new Date(adr.date);
            adr.createdAt = new Date(adr.createdAt);
            adr.updatedAt = new Date(adr.updatedAt);
            if (adr.statusHistory) {
                adr.statusHistory = adr.statusHistory.map((sh) => ({
                    ...sh,
                    date: new Date(sh.date)
                }));
            }
            return adr;
        }
        catch (error) {
            return null;
        }
    }
    async listADRs() {
        await this.ensureInitialized();
        try {
            const files = await fs.readdir(this.recordsPath);
            const adrIds = files
                .filter(f => f.match(/^ADR-\d{4}.*\.json$/))
                .map(f => f.match(/^(ADR-\d{4})/)?.[1])
                .filter(Boolean);
            // Sort numerically by ADR number
            return adrIds.sort((a, b) => {
                const numA = parseInt(a.replace('ADR-', ''));
                const numB = parseInt(b.replace('ADR-', ''));
                return numA - numB;
            });
        }
        catch (error) {
            return [];
        }
    }
    async getNextADRNumber() {
        const adrs = await this.listADRs();
        if (adrs.length === 0) {
            return '0001';
        }
        // Get the highest number
        const numbers = adrs.map(id => parseInt(id.replace('ADR-', '')));
        const maxNumber = Math.max(...numbers);
        return String(maxNumber + 1).padStart(4, '0');
    }
    async deleteADR(id) {
        await this.ensureInitialized();
        try {
            const files = await fs.readdir(this.recordsPath);
            const adrFile = files.find(f => f.startsWith(`${id}-`) && f.endsWith('.json'));
            if (adrFile) {
                const filepath = path.join(this.recordsPath, adrFile);
                await fs.unlink(filepath);
            }
        }
        catch (error) {
            // Ignore errors if file doesn't exist
        }
    }
    async saveIndex(index) {
        await this.ensureInitialized();
        const indexPath = path.join(this.recordsPath, 'index.json');
        await fs.writeFile(indexPath, JSON.stringify(index, null, 2), 'utf-8');
    }
    async loadIndex() {
        await this.ensureInitialized();
        try {
            const indexPath = path.join(this.recordsPath, 'index.json');
            const content = await fs.readFile(indexPath, 'utf-8');
            const index = JSON.parse(content);
            index.lastUpdated = new Date(index.lastUpdated);
            return index;
        }
        catch (error) {
            return null;
        }
    }
    async searchADRs(options) {
        await this.ensureInitialized();
        const allIds = await this.listADRs();
        const results = [];
        for (const id of allIds) {
            const adr = await this.loadADR(id);
            if (!adr)
                continue;
            let matches = true;
            // Check status filter
            if (options.status && options.status.length > 0) {
                matches = matches && options.status.includes(adr.status);
            }
            // Check query text
            if (options.query) {
                const query = options.query.toLowerCase();
                const searchText = [
                    adr.title,
                    adr.context,
                    adr.decision,
                    adr.consequences,
                    ...(adr.tags || [])
                ].join(' ').toLowerCase();
                matches = matches && searchText.includes(query);
            }
            // Check tags
            if (options.tags && options.tags.length > 0) {
                const adrTags = adr.tags || [];
                matches = matches && options.tags.some(tag => adrTags.includes(tag));
            }
            // Check template
            if (options.template) {
                matches = matches && adr.template === options.template;
            }
            // Check date range
            if (options.dateRange) {
                const adrDate = new Date(adr.date);
                matches = matches &&
                    adrDate >= options.dateRange.from &&
                    adrDate <= options.dateRange.to;
            }
            // Check deciders
            if (options.deciders && options.deciders.length > 0) {
                matches = matches && options.deciders.some(d => adr.deciders.includes(d));
            }
            if (matches) {
                results.push(adr);
            }
        }
        return results;
    }
    async exportToMarkdown(adr) {
        let markdown = `# ${adr.id}: ${adr.title}\n\n`;
        // Status section
        markdown += `## Status\n\n`;
        markdown += `${adr.status.charAt(0).toUpperCase() + adr.status.slice(1)}\n\n`;
        // Metadata
        markdown += `**Date**: ${adr.date.toISOString().split('T')[0]}\n`;
        markdown += `**Deciders**: ${adr.deciders.join(', ')}\n`;
        if (adr.tags && adr.tags.length > 0) {
            markdown += `**Tags**: ${adr.tags.join(', ')}\n`;
        }
        markdown += '\n';
        // Context
        markdown += `## Context\n\n${adr.context}\n\n`;
        // Decision drivers (MADR)
        if (adr.decisionDrivers && adr.decisionDrivers.length > 0) {
            markdown += `## Decision Drivers\n\n`;
            adr.decisionDrivers.forEach(driver => {
                markdown += `* ${driver}\n`;
            });
            markdown += '\n';
        }
        // Considered Options (MADR)
        if (adr.consideredOptions && adr.consideredOptions.length > 0) {
            markdown += `## Considered Options\n\n`;
            adr.consideredOptions.forEach(option => {
                markdown += `* ${option.title} - ${option.description}\n`;
            });
            markdown += '\n';
        }
        // Decision
        markdown += `## Decision\n\n${adr.decision}\n\n`;
        // Consequences
        markdown += `## Consequences\n\n${adr.consequences}\n\n`;
        // Pros and Cons per option (MADR)
        if (adr.consideredOptions && adr.consideredOptions.length > 0) {
            adr.consideredOptions.forEach(option => {
                markdown += `### ${option.title}\n\n`;
                if (option.description) {
                    markdown += `${option.description}\n\n`;
                }
                option.pros.forEach(pro => {
                    markdown += `* Good, because ${pro}\n`;
                });
                option.cons.forEach(con => {
                    markdown += `* Bad, because ${con}\n`;
                });
                markdown += '\n';
            });
        }
        // Links
        const hasLinks = adr.supersedes?.length || adr.supersededBy || adr.relatedTo?.length;
        if (hasLinks) {
            markdown += `## Links\n\n`;
            if (adr.supersedes && adr.supersedes.length > 0) {
                markdown += `* Supersedes: ${adr.supersedes.join(', ')}\n`;
            }
            if (adr.supersededBy) {
                markdown += `* Superseded by: ${adr.supersededBy}\n`;
            }
            if (adr.relatedTo && adr.relatedTo.length > 0) {
                markdown += `* Related to: ${adr.relatedTo.join(', ')}\n`;
            }
            markdown += '\n';
        }
        // Status History
        if (adr.statusHistory && adr.statusHistory.length > 0) {
            markdown += `## Status History\n\n`;
            adr.statusHistory.forEach(change => {
                markdown += `* ${change.from} → ${change.to} on ${change.date.toISOString().split('T')[0]}`;
                markdown += ` by ${change.changedBy}`;
                if (change.reason) {
                    markdown += `: ${change.reason}`;
                }
                markdown += '\n';
            });
        }
        return markdown;
    }
    async generateADRLog() {
        await this.ensureInitialized();
        const adrIds = await this.listADRs();
        let log = '# Architecture Decision Records\n\n';
        log += `This log contains all ADRs for the project.\n\n`;
        log += `Total ADRs: ${adrIds.length}\n\n`;
        for (const id of adrIds) {
            const adr = await this.loadADR(id);
            if (!adr)
                continue;
            const statusEmoji = {
                proposed: '💡',
                accepted: '✅',
                rejected: '❌',
                deprecated: '⚠️',
                superseded: '🔄'
            };
            log += `## ${statusEmoji[adr.status] || '📄'} ${adr.id}: ${adr.title}\n\n`;
            log += `**Status**: ${adr.status.charAt(0).toUpperCase() + adr.status.slice(1)}\n`;
            log += `**Date**: ${adr.date.toISOString().split('T')[0]}\n`;
            log += `**Deciders**: ${adr.deciders.join(', ')}\n\n`;
            // Brief summary
            const contextPreview = adr.context.split('\n')[0].substring(0, 200);
            log += `${contextPreview}${adr.context.length > 200 ? '...' : ''}\n\n`;
            log += '---\n\n';
        }
        return log;
    }
    async ensureInitialized() {
        if (!this.initialized) {
            await this.initialize();
        }
    }
}
//# sourceMappingURL=store.js.map