import { StorageManager } from '../../storage/storage-manager.js';
import { promises as fs } from 'fs';
import path from 'path';
export class RoadmapManager {
    configManager;
    storageManager;
    roadmapDataPath;
    roadmaps;
    themes;
    initiatives;
    features;
    milestones;
    releases;
    reviews;
    constructor(configManager) {
        this.configManager = configManager;
        this.storageManager = new StorageManager();
        this.roadmapDataPath = '';
        this.roadmaps = new Map();
        this.themes = new Map();
        this.initiatives = new Map();
        this.features = new Map();
        this.milestones = new Map();
        this.releases = new Map();
        this.reviews = new Map();
    }
    async initialize() {
        const location = await this.storageManager.getStorageLocation();
        this.roadmapDataPath = path.join(location.data, 'roadmaps');
        await this.loadExistingData();
    }
    async loadExistingData() {
        try {
            // Load roadmaps
            const roadmapsPath = path.join(this.roadmapDataPath, 'roadmaps.json');
            if (await this.fileExists(roadmapsPath)) {
                const roadmapsData = JSON.parse(await fs.readFile(roadmapsPath, 'utf-8'));
                roadmapsData.forEach((roadmap) => {
                    roadmap.createdAt = new Date(roadmap.createdAt);
                    roadmap.updatedAt = new Date(roadmap.updatedAt);
                    this.roadmaps.set(roadmap.id, roadmap);
                });
            }
            // Load themes
            const themesPath = path.join(this.roadmapDataPath, 'themes.json');
            if (await this.fileExists(themesPath)) {
                const themesData = JSON.parse(await fs.readFile(themesPath, 'utf-8'));
                themesData.forEach((theme) => {
                    this.themes.set(theme.id, theme);
                });
            }
            // Load initiatives
            const initiativesPath = path.join(this.roadmapDataPath, 'initiatives.json');
            if (await this.fileExists(initiativesPath)) {
                const initiativesData = JSON.parse(await fs.readFile(initiativesPath, 'utf-8'));
                initiativesData.forEach((initiative) => {
                    this.initiatives.set(initiative.id, initiative);
                });
            }
            // Load features
            const featuresPath = path.join(this.roadmapDataPath, 'features.json');
            if (await this.fileExists(featuresPath)) {
                const featuresData = JSON.parse(await fs.readFile(featuresPath, 'utf-8'));
                featuresData.forEach((feature) => {
                    this.features.set(feature.id, feature);
                });
            }
            // Load milestones
            const milestonesPath = path.join(this.roadmapDataPath, 'milestones.json');
            if (await this.fileExists(milestonesPath)) {
                const milestonesData = JSON.parse(await fs.readFile(milestonesPath, 'utf-8'));
                milestonesData.forEach((milestone) => {
                    milestone.date = new Date(milestone.date);
                    this.milestones.set(milestone.id, milestone);
                });
            }
            // Load releases
            const releasesPath = path.join(this.roadmapDataPath, 'releases.json');
            if (await this.fileExists(releasesPath)) {
                const releasesData = JSON.parse(await fs.readFile(releasesPath, 'utf-8'));
                releasesData.forEach((release) => {
                    release.date = new Date(release.date);
                    this.releases.set(release.id, release);
                });
            }
        }
        catch (error) {
            console.error('Error loading roadmap data:', error);
        }
    }
    async fileExists(filePath) {
        try {
            await fs.access(filePath);
            return true;
        }
        catch {
            return false;
        }
    }
    async createRoadmap(options) {
        const roadmap = {
            id: `roadmap-${this.generateId()}`,
            name: options.name,
            vision: options.vision,
            timeHorizon: options.timeHorizon,
            status: 'draft',
            themes: [],
            milestones: [],
            releases: [],
            createdAt: new Date(),
            updatedAt: new Date(),
            owner: options.owner,
            stakeholders: options.stakeholders || [],
            metrics: {
                featuresPlanned: 0,
                featuresCompleted: 0,
                initiativesActive: 0,
                velocityTrend: 'stable',
                onTimeDelivery: 100,
                valueDelivered: 0
            }
        };
        this.roadmaps.set(roadmap.id, roadmap);
        await this.saveRoadmaps();
        return roadmap;
    }
    async addTheme(options) {
        const roadmap = this.roadmaps.get(options.roadmapId);
        if (!roadmap) {
            throw new Error(`Roadmap ${options.roadmapId} not found`);
        }
        const theme = {
            id: `theme-${this.generateId()}`,
            name: options.name,
            description: options.description,
            objectives: options.objectives,
            initiatives: [],
            priority: options.priority,
            timeframe: {
                startQuarter: options.startQuarter,
                endQuarter: options.endQuarter
            },
            status: 'planned',
            metrics: {
                initiativesTotal: 0,
                initiativesCompleted: 0,
                featuresTotal: 0,
                featuresCompleted: 0,
                progressPercentage: 0,
                valueScore: 0
            }
        };
        this.themes.set(theme.id, theme);
        roadmap.themes.push(theme);
        roadmap.updatedAt = new Date();
        await Promise.all([this.saveThemes(), this.saveRoadmaps()]);
        return theme;
    }
    async createInitiative(options) {
        const roadmap = this.roadmaps.get(options.roadmapId);
        const theme = this.themes.get(options.themeId);
        if (!roadmap) {
            throw new Error(`Roadmap ${options.roadmapId} not found`);
        }
        if (!theme) {
            throw new Error(`Theme ${options.themeId} not found`);
        }
        const initiative = {
            id: `initiative-${this.generateId()}`,
            themeId: options.themeId,
            title: options.title,
            description: options.description,
            features: [],
            epicIds: [],
            value: options.estimatedValue,
            effort: options.estimatedEffort,
            risks: options.risks || [],
            dependencies: [],
            status: 'ideation'
        };
        this.initiatives.set(initiative.id, initiative);
        theme.initiatives.push(initiative);
        // Update theme metrics
        theme.metrics.initiativesTotal++;
        this.updateRoadmapMetrics(roadmap);
        await Promise.all([
            this.saveInitiatives(),
            this.saveThemes(),
            this.saveRoadmaps()
        ]);
        return initiative;
    }
    async addFeature(options) {
        const roadmap = this.roadmaps.get(options.roadmapId);
        const initiative = this.initiatives.get(options.initiativeId);
        if (!roadmap) {
            throw new Error(`Roadmap ${options.roadmapId} not found`);
        }
        if (!initiative) {
            throw new Error(`Initiative ${options.initiativeId} not found`);
        }
        const feature = {
            id: `feature-${this.generateId()}`,
            initiativeId: options.initiativeId,
            name: options.name,
            description: options.description,
            userStories: [],
            priority: 0, // Will be set by prioritization
            businessValue: options.businessValue,
            technicalComplexity: options.technicalComplexity,
            targetRelease: options.targetRelease,
            status: 'proposed'
        };
        this.features.set(feature.id, feature);
        initiative.features.push(feature);
        // Update metrics
        const theme = this.themes.get(initiative.themeId);
        if (theme) {
            theme.metrics.featuresTotal++;
        }
        roadmap.metrics.featuresPlanned++;
        this.updateRoadmapMetrics(roadmap);
        await Promise.all([
            this.saveFeatures(),
            this.saveInitiatives(),
            this.saveThemes(),
            this.saveRoadmaps()
        ]);
        return feature;
    }
    async createMilestone(roadmapId, milestone) {
        const roadmap = this.roadmaps.get(roadmapId);
        if (!roadmap) {
            throw new Error(`Roadmap ${roadmapId} not found`);
        }
        const newMilestone = {
            ...milestone,
            id: `milestone-${this.generateId()}`,
            date: new Date(milestone.date),
            status: 'upcoming'
        };
        this.milestones.set(newMilestone.id, newMilestone);
        roadmap.milestones.push(newMilestone);
        roadmap.updatedAt = new Date();
        await Promise.all([this.saveMilestones(), this.saveRoadmaps()]);
        return newMilestone;
    }
    async planRelease(roadmapId, release) {
        const roadmap = this.roadmaps.get(roadmapId);
        if (!roadmap) {
            throw new Error(`Roadmap ${roadmapId} not found`);
        }
        const newRelease = {
            ...release,
            id: `release-${this.generateId()}`,
            date: new Date(release.date),
            status: 'planning'
        };
        this.releases.set(newRelease.id, newRelease);
        roadmap.releases.push(newRelease);
        roadmap.updatedAt = new Date();
        await Promise.all([this.saveReleases(), this.saveRoadmaps()]);
        return newRelease;
    }
    async updateFeatureStatus(featureId, status) {
        const feature = this.features.get(featureId);
        if (!feature) {
            throw new Error(`Feature ${featureId} not found`);
        }
        feature.status = status;
        // Update metrics if completed
        if (status === 'completed') {
            const initiative = this.initiatives.get(feature.initiativeId);
            if (initiative) {
                const theme = this.themes.get(initiative.themeId);
                if (theme) {
                    theme.metrics.featuresCompleted++;
                    this.updateThemeProgress(theme);
                }
            }
            // Find and update roadmap
            for (const [, roadmap] of this.roadmaps) {
                if (roadmap.themes.some(t => t.id === initiative?.themeId)) {
                    roadmap.metrics.featuresCompleted++;
                    this.updateRoadmapMetrics(roadmap);
                    break;
                }
            }
        }
        await this.saveFeatures();
        return feature;
    }
    async updateInitiativeStatus(initiativeId, status) {
        const initiative = this.initiatives.get(initiativeId);
        if (!initiative) {
            throw new Error(`Initiative ${initiativeId} not found`);
        }
        initiative.status = status;
        // Update theme metrics if completed
        if (status === 'launched') {
            const theme = this.themes.get(initiative.themeId);
            if (theme) {
                theme.metrics.initiativesCompleted++;
                this.updateThemeProgress(theme);
            }
        }
        await this.saveInitiatives();
        return initiative;
    }
    async generateTimeline(roadmapId, viewType) {
        const roadmap = this.roadmaps.get(roadmapId);
        if (!roadmap) {
            throw new Error(`Roadmap ${roadmapId} not found`);
        }
        const items = [];
        const now = new Date();
        // Add themes to timeline
        for (const theme of roadmap.themes) {
            const startDate = this.parseQuarter(theme.timeframe.startQuarter);
            const endDate = this.parseQuarter(theme.timeframe.endQuarter);
            items.push({
                id: theme.id,
                type: 'theme',
                name: theme.name,
                startDate,
                endDate,
                status: theme.status,
                dependencies: [],
                progress: theme.metrics.progressPercentage
            });
        }
        // Add milestones
        for (const milestone of roadmap.milestones) {
            items.push({
                id: milestone.id,
                type: 'milestone',
                name: milestone.name,
                startDate: milestone.date,
                endDate: milestone.date,
                status: milestone.status,
                dependencies: milestone.dependencies
            });
        }
        // Add releases
        for (const release of roadmap.releases) {
            items.push({
                id: release.id,
                type: 'release',
                name: `${release.version} - ${release.name}`,
                startDate: release.date,
                endDate: release.date,
                status: release.status,
                dependencies: []
            });
        }
        // Sort by start date
        items.sort((a, b) => a.startDate.getTime() - b.startDate.getTime());
        return {
            type: viewType,
            startDate: items[0]?.startDate || now,
            endDate: items[items.length - 1]?.endDate || now,
            items
        };
    }
    async getRoadmapHealth(roadmapId) {
        const roadmap = this.roadmaps.get(roadmapId);
        if (!roadmap) {
            throw new Error(`Roadmap ${roadmapId} not found`);
        }
        const risks = [];
        const recommendations = [];
        // Analyze on-time delivery
        if (roadmap.metrics.onTimeDelivery < 70) {
            risks.push('Low on-time delivery rate');
            recommendations.push('Review capacity planning and estimates');
        }
        // Check velocity trend
        if (roadmap.metrics.velocityTrend === 'decreasing') {
            risks.push('Decreasing velocity trend');
            recommendations.push('Investigate blockers and team capacity');
        }
        // Calculate health score
        let healthScore = 100;
        if (roadmap.metrics.onTimeDelivery < 80)
            healthScore -= 20;
        if (roadmap.metrics.velocityTrend === 'decreasing')
            healthScore -= 20;
        if (roadmap.metrics.featuresCompleted / roadmap.metrics.featuresPlanned < 0.5)
            healthScore -= 20;
        const health = healthScore >= 80 ? 'excellent' :
            healthScore >= 60 ? 'good' :
                healthScore >= 40 ? 'at-risk' : 'critical';
        return {
            health,
            metrics: roadmap.metrics,
            risks,
            recommendations
        };
    }
    async getRoadmaps() {
        return Array.from(this.roadmaps.values())
            .filter(r => r.status !== 'archived')
            .sort((a, b) => b.updatedAt.getTime() - a.updatedAt.getTime());
    }
    async getRoadmap(roadmapId) {
        return this.roadmaps.get(roadmapId) || null;
    }
    async getThemeDetails(themeId) {
        const theme = this.themes.get(themeId);
        if (!theme)
            return null;
        const initiatives = theme.initiatives.map(i => this.initiatives.get(typeof i === 'string' ? i : i.id)).filter(Boolean);
        const features = [];
        for (const initiative of initiatives) {
            const initiativeFeatures = initiative.features.map(f => this.features.get(typeof f === 'string' ? f : f.id)).filter(Boolean);
            features.push(...initiativeFeatures);
        }
        return { theme, initiatives, features };
    }
    updateRoadmapMetrics(roadmap) {
        // Count active initiatives
        let activeInitiatives = 0;
        for (const theme of roadmap.themes) {
            for (const initiative of theme.initiatives) {
                const init = typeof initiative === 'string' ?
                    this.initiatives.get(initiative) : initiative;
                if (init && ['validated', 'scheduled', 'in-development'].includes(init.status)) {
                    activeInitiatives++;
                }
            }
        }
        roadmap.metrics.initiativesActive = activeInitiatives;
        // Calculate value delivered
        let totalValue = 0;
        let completedValue = 0;
        for (const feature of this.features.values()) {
            if (feature.status === 'completed') {
                completedValue += feature.businessValue.score;
            }
            totalValue += feature.businessValue.score;
        }
        roadmap.metrics.valueDelivered = totalValue > 0 ?
            Math.round((completedValue / totalValue) * 100) : 0;
    }
    updateThemeProgress(theme) {
        const total = theme.metrics.initiativesTotal + theme.metrics.featuresTotal;
        const completed = theme.metrics.initiativesCompleted + theme.metrics.featuresCompleted;
        theme.metrics.progressPercentage = total > 0 ?
            Math.round((completed / total) * 100) : 0;
    }
    parseQuarter(quarter) {
        // Parse "Q1 2024" format
        const [q, year] = quarter.split(' ');
        const quarterNum = parseInt(q.substring(1));
        const yearNum = parseInt(year);
        // Q1 = Jan, Q2 = Apr, Q3 = Jul, Q4 = Oct
        const month = (quarterNum - 1) * 3;
        return new Date(yearNum, month, 1);
    }
    generateId() {
        return `${Date.now().toString(16)}-${Math.random().toString(16).substr(2, 8)}`;
    }
    // Save methods
    async saveRoadmaps() {
        const roadmapsPath = path.join(this.roadmapDataPath, 'roadmaps.json');
        await fs.mkdir(path.dirname(roadmapsPath), { recursive: true });
        await fs.writeFile(roadmapsPath, JSON.stringify(Array.from(this.roadmaps.values()), null, 2));
    }
    async saveThemes() {
        const themesPath = path.join(this.roadmapDataPath, 'themes.json');
        await fs.mkdir(path.dirname(themesPath), { recursive: true });
        await fs.writeFile(themesPath, JSON.stringify(Array.from(this.themes.values()), null, 2));
    }
    async saveInitiatives() {
        const initiativesPath = path.join(this.roadmapDataPath, 'initiatives.json');
        await fs.mkdir(path.dirname(initiativesPath), { recursive: true });
        await fs.writeFile(initiativesPath, JSON.stringify(Array.from(this.initiatives.values()), null, 2));
    }
    async saveFeatures() {
        const featuresPath = path.join(this.roadmapDataPath, 'features.json');
        await fs.mkdir(path.dirname(featuresPath), { recursive: true });
        await fs.writeFile(featuresPath, JSON.stringify(Array.from(this.features.values()), null, 2));
    }
    async saveMilestones() {
        const milestonesPath = path.join(this.roadmapDataPath, 'milestones.json');
        await fs.mkdir(path.dirname(milestonesPath), { recursive: true });
        await fs.writeFile(milestonesPath, JSON.stringify(Array.from(this.milestones.values()), null, 2));
    }
    async saveReleases() {
        const releasesPath = path.join(this.roadmapDataPath, 'releases.json');
        await fs.mkdir(path.dirname(releasesPath), { recursive: true });
        await fs.writeFile(releasesPath, JSON.stringify(Array.from(this.releases.values()), null, 2));
    }
}
//# sourceMappingURL=roadmap-manager.js.map