import { readFile, readdir, access, stat } from 'fs/promises';
import { join } from 'path';
import { PathUtils } from '../core/path-utils.js';
import { parseTaskProgress } from '../core/task-parser.js';
export class SpecParser {
    projectPath;
    specsPath;
    archiveSpecsPath;
    steeringPath;
    constructor(projectPath) {
        // Path should already be translated by caller (ProjectManager)
        this.projectPath = projectPath;
        this.specsPath = PathUtils.getSpecPath(projectPath, '');
        this.archiveSpecsPath = PathUtils.getArchiveSpecsPath(projectPath);
        this.steeringPath = PathUtils.getSteeringPath(projectPath);
    }
    async getAllSpecs() {
        try {
            await access(this.specsPath);
            const entries = await readdir(this.specsPath, { withFileTypes: true });
            const specDirs = entries.filter(entry => entry.isDirectory());
            const specs = [];
            for (const dir of specDirs) {
                const spec = await this.getSpec(dir.name);
                if (spec) {
                    specs.push(spec);
                }
            }
            return specs.sort((a, b) => a.name.localeCompare(b.name));
        }
        catch {
            return [];
        }
    }
    async getAllArchivedSpecs() {
        try {
            await access(this.archiveSpecsPath);
            const entries = await readdir(this.archiveSpecsPath, { withFileTypes: true });
            const specDirs = entries.filter(entry => entry.isDirectory());
            const specs = [];
            for (const dir of specDirs) {
                const spec = await this.getArchivedSpec(dir.name);
                if (spec) {
                    specs.push(spec);
                }
            }
            return specs.sort((a, b) => a.name.localeCompare(b.name));
        }
        catch {
            return [];
        }
    }
    async getSpec(name) {
        try {
            const specDir = PathUtils.getSpecPath(this.projectPath, name);
            await access(specDir);
            const spec = {
                name,
                displayName: this.formatDisplayName(name),
                createdAt: '',
                lastModified: '',
                phases: {
                    requestSpec: { exists: false },
                    requirements: { exists: false },
                    design: { exists: false },
                    testDesign: { exists: false },
                    tasks: { exists: false },
                    implementation: { exists: false }
                }
            };
            // Get directory stats
            const dirStats = await stat(specDir);
            spec.createdAt = dirStats.birthtime.toISOString();
            spec.lastModified = dirStats.mtime.toISOString();
            // Check each phase
            const requestSpecPath = join(specDir, 'request-spec.md');
            const requirementsPath = join(specDir, 'requirements.md');
            const designPath = join(specDir, 'design.md');
            const testDesignPath = join(specDir, 'test-design.md');
            const tasksPath = join(specDir, 'tasks.md');
            // Check request spec
            try {
                await access(requestSpecPath);
                spec.phases.requestSpec.exists = true;
                const reqSpecStats = await stat(requestSpecPath);
                spec.phases.requestSpec.lastModified = reqSpecStats.mtime.toISOString();
                if (reqSpecStats.mtime > new Date(spec.lastModified)) {
                    spec.lastModified = reqSpecStats.mtime.toISOString();
                }
            }
            catch { }
            // Check requirements
            try {
                await access(requirementsPath);
                spec.phases.requirements.exists = true;
                const reqStats = await stat(requirementsPath);
                spec.phases.requirements.lastModified = reqStats.mtime.toISOString();
                // Update overall last modified if this is newer
                if (reqStats.mtime > new Date(spec.lastModified)) {
                    spec.lastModified = reqStats.mtime.toISOString();
                }
            }
            catch { }
            // Check design
            try {
                await access(designPath);
                spec.phases.design.exists = true;
                const designStats = await stat(designPath);
                spec.phases.design.lastModified = designStats.mtime.toISOString();
                if (designStats.mtime > new Date(spec.lastModified)) {
                    spec.lastModified = designStats.mtime.toISOString();
                }
            }
            catch { }
            // Check test design
            try {
                await access(testDesignPath);
                spec.phases.testDesign.exists = true;
                const testDesignStats = await stat(testDesignPath);
                spec.phases.testDesign.lastModified = testDesignStats.mtime.toISOString();
                if (testDesignStats.mtime > new Date(spec.lastModified)) {
                    spec.lastModified = testDesignStats.mtime.toISOString();
                }
            }
            catch { }
            // Check tasks
            try {
                await access(tasksPath);
                spec.phases.tasks.exists = true;
                const tasksStats = await stat(tasksPath);
                spec.phases.tasks.lastModified = tasksStats.mtime.toISOString();
                if (tasksStats.mtime > new Date(spec.lastModified)) {
                    spec.lastModified = tasksStats.mtime.toISOString();
                }
                // Parse tasks to get progress
                const tasksContent = await readFile(tasksPath, 'utf-8');
                const taskProgress = parseTaskProgress(tasksContent);
                spec.taskProgress = {
                    total: taskProgress.total,
                    completed: taskProgress.completed,
                    pending: taskProgress.pending
                };
            }
            catch { }
            // Implementation phase is always considered "exists" since it's ongoing manual work
            spec.phases.implementation.exists = true;
            return spec;
        }
        catch {
            return null;
        }
    }
    async getArchivedSpec(name) {
        try {
            const specDir = PathUtils.getArchiveSpecPath(this.projectPath, name);
            await access(specDir);
            const spec = {
                name,
                displayName: this.formatDisplayName(name),
                createdAt: '',
                lastModified: '',
                phases: {
                    requestSpec: { exists: false },
                    requirements: { exists: false },
                    design: { exists: false },
                    testDesign: { exists: false },
                    tasks: { exists: false },
                    implementation: { exists: false }
                }
            };
            // Get directory stats
            const dirStats = await stat(specDir);
            spec.createdAt = dirStats.birthtime.toISOString();
            spec.lastModified = dirStats.mtime.toISOString();
            // Check each phase
            const requestSpecPath = join(specDir, 'request-spec.md');
            const requirementsPath = join(specDir, 'requirements.md');
            const designPath = join(specDir, 'design.md');
            const testDesignPath = join(specDir, 'test-design.md');
            const tasksPath = join(specDir, 'tasks.md');
            // Check request spec
            try {
                await access(requestSpecPath);
                spec.phases.requestSpec.exists = true;
                const reqSpecStats = await stat(requestSpecPath);
                spec.phases.requestSpec.lastModified = reqSpecStats.mtime.toISOString();
                if (reqSpecStats.mtime > new Date(spec.lastModified)) {
                    spec.lastModified = reqSpecStats.mtime.toISOString();
                }
            }
            catch { }
            // Check requirements
            try {
                await access(requirementsPath);
                spec.phases.requirements.exists = true;
                const reqStats = await stat(requirementsPath);
                spec.phases.requirements.lastModified = reqStats.mtime.toISOString();
                // Update overall last modified if this is newer
                if (reqStats.mtime > new Date(spec.lastModified)) {
                    spec.lastModified = reqStats.mtime.toISOString();
                }
            }
            catch { }
            // Check design
            try {
                await access(designPath);
                spec.phases.design.exists = true;
                const designStats = await stat(designPath);
                spec.phases.design.lastModified = designStats.mtime.toISOString();
                if (designStats.mtime > new Date(spec.lastModified)) {
                    spec.lastModified = designStats.mtime.toISOString();
                }
            }
            catch { }
            // Check test design
            try {
                await access(testDesignPath);
                spec.phases.testDesign.exists = true;
                const testDesignStats = await stat(testDesignPath);
                spec.phases.testDesign.lastModified = testDesignStats.mtime.toISOString();
                if (testDesignStats.mtime > new Date(spec.lastModified)) {
                    spec.lastModified = testDesignStats.mtime.toISOString();
                }
            }
            catch { }
            // Check tasks
            try {
                await access(tasksPath);
                spec.phases.tasks.exists = true;
                const tasksStats = await stat(tasksPath);
                spec.phases.tasks.lastModified = tasksStats.mtime.toISOString();
                if (tasksStats.mtime > new Date(spec.lastModified)) {
                    spec.lastModified = tasksStats.mtime.toISOString();
                }
                // Parse tasks to get progress
                const tasksContent = await readFile(tasksPath, 'utf-8');
                const taskProgress = parseTaskProgress(tasksContent);
                spec.taskProgress = {
                    total: taskProgress.total,
                    completed: taskProgress.completed,
                    pending: taskProgress.pending
                };
            }
            catch { }
            // Implementation phase is always considered "exists" since it's ongoing manual work
            spec.phases.implementation.exists = true;
            return spec;
        }
        catch {
            return null;
        }
    }
    async getProjectSteeringStatus() {
        const status = {
            exists: false,
            documents: {
                product: false,
                tech: false,
                structure: false
            }
        };
        try {
            await access(this.steeringPath);
            status.exists = true;
            // Check each steering document
            try {
                await access(join(this.steeringPath, 'product.md'));
                status.documents.product = true;
            }
            catch { }
            try {
                await access(join(this.steeringPath, 'tech.md'));
                status.documents.tech = true;
            }
            catch { }
            try {
                await access(join(this.steeringPath, 'structure.md'));
                status.documents.structure = true;
            }
            catch { }
            // Get last modified time for steering directory
            const steeringStats = await stat(this.steeringPath);
            status.lastModified = steeringStats.mtime.toISOString();
        }
        catch { }
        return status;
    }
    formatDisplayName(kebabCase) {
        return kebabCase
            .split('-')
            .map(word => word.charAt(0).toUpperCase() + word.slice(1))
            .join(' ');
    }
}
//# sourceMappingURL=parser.js.map