/**
 * External Sync Orchestrator
 *
 * Coordinates syncing user stories to multiple external tools based on
 * per-US project targeting. Groups USs by their target project and
 * syncs each group to the appropriate external system.
 *
 * @module core/living-docs/external-sync-orchestrator
 * @since v0.33.0
 */
import * as path from 'node:path';
import { consoleLogger } from '../../utils/logger.js';
import { pathExists, readJson } from './sync-helpers/file-utils.js';
/**
 * External Sync Orchestrator
 */
export class ExternalSyncOrchestrator {
    constructor(projectRoot, options = {}) {
        this.projectMappings = {};
        this.projectRoot = projectRoot;
        this.logger = options.logger ?? consoleLogger;
        this.toolRegistry = options.toolRegistry;
    }
    /**
     * Set the tool registry for intelligent tool selection
     */
    setToolRegistry(registry) {
        this.toolRegistry = registry;
    }
    /**
     * Search for best sync tool matching project configuration
     *
     * Uses Tool Search Registry to find the optimal sync tool based on
     * project mapping (github, jira, ado).
     *
     * @param projectId - Project ID to find sync tool for
     * @returns Best matching tool result or null
     */
    async findSyncTool(projectId) {
        if (!this.toolRegistry) {
            return null;
        }
        const mapping = this.projectMappings[projectId];
        if (!mapping) {
            return null;
        }
        // Build query based on configured providers
        const providers = [];
        if (mapping.github)
            providers.push('github');
        if (mapping.jira)
            providers.push('jira');
        if (mapping.ado)
            providers.push('azure devops', 'ado');
        if (providers.length === 0) {
            return null;
        }
        const query = `sync ${providers.join(' ')} issues`;
        const result = await this.toolRegistry.findBestMatch(query);
        if (result && result.score > 0.3) {
            this.toolRegistry.recordToolSelection(result.tool.id, query, result.score, `project:${projectId}`);
            return result;
        }
        return null;
    }
    /**
     * Get loaded sync tool for a project
     *
     * Combines findSyncTool with lazy loading to get full tool content.
     *
     * @param projectId - Project ID
     * @returns Loaded tool with content or null
     */
    async getLoadedSyncTool(projectId) {
        if (!this.toolRegistry) {
            return null;
        }
        const result = await this.findSyncTool(projectId);
        if (!result) {
            return null;
        }
        return this.toolRegistry.getLoadedTool(result.tool.id);
    }
    /**
     * Load project mappings from config
     */
    async loadProjectMappings() {
        const configPath = path.join(this.projectRoot, '.specweave/config.json');
        if (await pathExists(configPath)) {
            try {
                const config = await readJson(configPath);
                this.projectMappings = config.projectMappings || {};
            }
            catch (error) {
                this.logger.warn('Failed to load projectMappings from config');
            }
        }
    }
    /**
     * Get project mapping for a project ID
     */
    getProjectMapping(projectId) {
        return this.projectMappings[projectId];
    }
    /**
     * Group user stories by their target project
     */
    groupUSsByProject(userStories, defaultProject) {
        const groups = new Map();
        for (const us of userStories) {
            const project = us.project || defaultProject;
            if (!groups.has(project)) {
                groups.set(project, []);
            }
            groups.get(project).push(us);
        }
        return groups;
    }
    /**
     * Get preferred provider for a US
     * Priority: US.externalProvider > first available in mapping
     */
    getPreferredProvider(us, mapping) {
        // Explicit preference in US
        if (us.externalProvider && mapping[us.externalProvider]) {
            return us.externalProvider;
        }
        // Fall back to first available in mapping
        if (mapping.github)
            return 'github';
        if (mapping.jira)
            return 'jira';
        if (mapping.ado)
            return 'ado';
        return null;
    }
    /**
     * Build external refs map from sync results
     */
    buildExternalRefsMap(results) {
        const refsMap = {};
        for (const projectResult of results) {
            for (const usResult of projectResult.synced) {
                if (!usResult.success)
                    continue;
                if (!refsMap[usResult.usId]) {
                    refsMap[usResult.usId] = {};
                }
                refsMap[usResult.usId][usResult.provider] = {
                    provider: usResult.provider,
                    issueNumber: usResult.issueNumber,
                    url: usResult.url,
                    targetProject: projectResult.projectId,
                    lastSynced: new Date().toISOString()
                };
            }
        }
        return refsMap;
    }
    /**
     * Log sync summary
     */
    logSyncSummary(result) {
        this.logger.log('');
        this.logger.log('🔗 Cross-Project External Sync Summary:');
        this.logger.log(`   Projects: ${result.summary.projectCount}`);
        this.logger.log(`   User Stories: ${result.summary.syncedUSs}/${result.summary.totalUSs} synced`);
        for (const project of result.projects) {
            const status = project.success ? '✅' : '❌';
            this.logger.log(`   ${status} ${project.projectId} (${project.provider}): ${project.synced.length} USs`);
            if (project.errors.length > 0) {
                for (const error of project.errors) {
                    this.logger.warn(`      ⚠️ ${error}`);
                }
            }
        }
    }
    /**
     * Create placeholder sync result for dry-run or when sync is skipped
     */
    createPlaceholderResult(userStories, defaultProject) {
        const groups = this.groupUSsByProject(userStories, defaultProject);
        return {
            success: true,
            projects: [...groups.entries()].map(([projectId, stories]) => ({
                projectId,
                provider: 'github',
                success: true,
                synced: stories.map(us => ({
                    usId: us.id,
                    provider: 'github',
                    success: false,
                    error: 'Sync skipped (dry-run or SKIP_EXTERNAL_SYNC)'
                })),
                errors: []
            })),
            externalRefs: {},
            summary: {
                totalUSs: userStories.length,
                syncedUSs: 0,
                failedUSs: 0,
                projectCount: groups.size
            }
        };
    }
}
//# sourceMappingURL=external-sync-orchestrator.js.map