// engine/pm-integrator.ts — PM platform integration orchestrator for SPEC-023b
// Re-exports creators from pm-platform-creators; owns validation, status sync, link logic.
import { generateLabels, createIssueJira, createIssueLinear, createIssueGithubProjects, createTaskTrello, createPageNotion, buildJiraBaseUrl, buildJiraAuthHeader, } from './pm-platform-creators.js';
// Re-export for backward compatibility (tests import from pm-integrator.ts)
export { generateLabels, createIssueJira, createIssueLinear, createIssueGithubProjects, createTaskTrello, createPageNotion, };
// === API key validation ===
/**
 * Validate that an API key is configured for the requested platform.
 * Returns the PMConfig when valid, or a descriptive error string when not.
 * Criteria 9: PM integrations require API keys configured by the user.
 */
export function validateApiKey(store, platform) {
    const config = store.platforms[platform];
    if (!config) {
        return (`API key not configured for platform "${platform}". ` +
            `Create data/global/pm-config.json with a "platforms.${platform}" entry containing ` +
            `"apiKey", "projectId", and optional "baseUrl" and "fieldMapping" fields.`);
    }
    if (!config.apiKey || config.apiKey.trim() === '') {
        return (`API key is empty for platform "${platform}". ` +
            `Set a valid "apiKey" in data/global/pm-config.json under platforms.${platform}.`);
    }
    return config;
}
// === Status mapping ===
const STATUS_MAPS = {
    jira: {
        draft: 'To Do',
        review: 'In Review',
        approved: 'Ready',
        implementing: 'In Progress',
        done: 'Done',
    },
    linear: {
        draft: 'Backlog',
        review: 'In Review',
        approved: 'Todo',
        implementing: 'In Progress',
        done: 'Done',
    },
    'github-projects': {
        draft: 'open',
        review: 'open',
        approved: 'open',
        implementing: 'open',
        done: 'closed',
    },
    trello: {
        draft: 'Backlog',
        review: 'Review',
        approved: 'Ready',
        implementing: 'Doing',
        done: 'Done',
    },
    notion: {
        draft: 'Draft',
        review: 'In Review',
        approved: 'Approved',
        implementing: 'In Progress',
        done: 'Done',
    },
};
/**
 * Map a spec status to the platform-native status string.
 */
export function mapSpecStatus(platform, specStatus) {
    return STATUS_MAPS[platform][specStatus] ?? specStatus;
}
function buildIssueUrl(platform, issueId, config) {
    if (platform === 'jira') {
        const domain = config.fieldMapping.domain ?? 'your-domain';
        return `https://${domain}.atlassian.net/browse/${issueId}`;
    }
    if (platform === 'linear') {
        return `https://linear.app/issue/${issueId}`;
    }
    if (platform === 'github-projects') {
        const owner = config.fieldMapping.owner ?? 'owner';
        const repo = config.fieldMapping.repo ?? config.projectId;
        return `https://github.com/${owner}/${repo}/issues/${issueId}`;
    }
    if (platform === 'trello') {
        return `https://trello.com/c/${issueId}`;
    }
    // notion
    return `https://notion.so/${issueId.replace(/-/g, '')}`;
}
// === Status sync per platform ===
async function syncJiraStatus(issueId, status, config) {
    const baseUrl = buildJiraBaseUrl(config);
    const response = await fetch(`${baseUrl}/issue/${issueId}/transitions`, {
        method: 'POST',
        headers: {
            Authorization: buildJiraAuthHeader(config),
            'Content-Type': 'application/json',
        },
        body: JSON.stringify({ transition: { name: status } }),
        signal: AbortSignal.timeout(10_000),
    });
    if (!response.ok) {
        const text = await response.text();
        throw new Error(`Jira status sync error ${response.status}: ${text}`);
    }
}
async function syncLinearStatus(issueId, status, config) {
    const mutation = `mutation UpdateIssue($id: String!, $input: IssueUpdateInput!) {
    issueUpdate(id: $id, input: $input) { success }
  }`;
    const linearUrl = config.baseUrl ?? 'https://api.linear.app/graphql';
    const response = await fetch(linearUrl, {
        method: 'POST',
        headers: { Authorization: config.apiKey, 'Content-Type': 'application/json' },
        body: JSON.stringify({
            query: mutation,
            variables: { id: issueId, input: { stateName: status } },
        }),
        signal: AbortSignal.timeout(10_000),
    });
    if (!response.ok) {
        const text = await response.text();
        throw new Error(`Linear status sync error ${response.status}: ${text}`);
    }
}
async function syncGithubStatus(issueId, status, config) {
    const owner = config.fieldMapping.owner ?? 'owner';
    const repo = config.fieldMapping.repo ?? config.projectId;
    const baseUrl = config.baseUrl ?? 'https://api.github.com';
    const state = status === 'closed' ? 'closed' : 'open';
    const response = await fetch(`${baseUrl}/repos/${owner}/${repo}/issues/${issueId}`, {
        method: 'PATCH',
        headers: {
            Authorization: `Bearer ${config.apiKey}`,
            'Content-Type': 'application/json',
            Accept: 'application/vnd.github+json',
        },
        body: JSON.stringify({ state }),
        signal: AbortSignal.timeout(10_000),
    });
    if (!response.ok) {
        const text = await response.text();
        throw new Error(`GitHub status sync error ${response.status}: ${text}`);
    }
}
/**
 * Sync spec status with the PM platform.
 * Criteria 6: integrate_pm syncs spec status with the platform.
 */
export async function syncSpecStatus(spec, issueId, platform, config) {
    const labels = generateLabels(spec);
    const mappedStatus = mapSpecStatus(platform, spec.status);
    if (platform === 'jira') {
        await syncJiraStatus(issueId, mappedStatus, config);
    }
    else if (platform === 'linear') {
        await syncLinearStatus(issueId, mappedStatus, config);
    }
    else if (platform === 'github-projects') {
        await syncGithubStatus(issueId, mappedStatus, config);
    }
    // Trello and Notion don't have a simple status-only update — treated as updated
    return {
        platform,
        issueId,
        issueUrl: buildIssueUrl(platform, issueId, config),
        status: 'updated',
        labels,
    };
}
/**
 * Link a spec to an existing issue/task in the PM platform.
 * Criteria 7: integrate_pm links specs with existing issues/tasks.
 */
export function linkSpecToIssue(spec, issueId, platform, config) {
    const labels = generateLabels(spec);
    return {
        platform,
        issueId,
        issueUrl: buildIssueUrl(platform, issueId, config),
        status: 'linked',
        labels,
    };
}
//# sourceMappingURL=pm-integrator.js.map