import { setTimeout as sleep } from 'node:timers/promises';
import { StructuredError } from '@agentuity/core';
import { APIResponseSchema } from '@agentuity/server';
import { z } from 'zod';
const GithubStartDataSchema = z.object({
    shortId: z.string(),
    hasIdentity: z.boolean(),
});
const GithubInstallationSchema = z.object({
    installationId: z.string(),
    integrationId: z.string().optional(),
    accountName: z.string(),
    accountType: z.enum(['User', 'Organization']),
    avatarUrl: z.string().optional(),
});
const GithubStatusDataSchema = z.object({
    connected: z.boolean(),
    identity: z
        .object({
        githubUsername: z.string(),
        githubEmail: z.string().optional(),
        avatarUrl: z.string().optional(),
    })
        .nullable(),
    installations: z.array(GithubInstallationSchema),
});
const GithubIntegrationStartError = StructuredError('GithubIntegrationStartError', 'Error starting GitHub integration flow');
export async function startGithubIntegration(apiClient) {
    const resp = await apiClient.get('/cli/github/start', APIResponseSchema(GithubStartDataSchema));
    if (!resp.success) {
        throw new GithubIntegrationStartError();
    }
    if (!resp.data) {
        throw new GithubIntegrationStartError();
    }
    return { shortId: resp.data.shortId, hasIdentity: resp.data.hasIdentity };
}
const GithubIntegrationStatusError = StructuredError('GithubIntegrationStatusError', 'Error checking GitHub integration status');
export async function getGithubIntegrationStatus(apiClient) {
    const resp = await apiClient.get('/cli/github/status', APIResponseSchema(GithubStatusDataSchema));
    if (!resp.success) {
        throw new GithubIntegrationStatusError();
    }
    if (!resp.data) {
        throw new GithubIntegrationStatusError();
    }
    return {
        connected: resp.data.connected,
        identity: resp.data.identity,
        installations: resp.data.installations,
    };
}
const GithubDisconnectDataSchema = z.object({
    disconnected: z.boolean(),
});
const GithubDisconnectError = StructuredError('GithubDisconnectError', 'Error disconnecting GitHub integration');
export async function disconnectGithubIntegration(apiClient, installationId) {
    let url = '/cli/github/disconnect';
    if (installationId) {
        url += `?installationId=${encodeURIComponent(installationId)}`;
    }
    const resp = await apiClient.delete(url, APIResponseSchema(GithubDisconnectDataSchema));
    if (!resp.success) {
        throw new GithubDisconnectError();
    }
    if (!resp.data) {
        throw new GithubDisconnectError();
    }
    return { disconnected: resp.data.disconnected };
}
// Polling
const PollForGithubIntegrationError = StructuredError('PollForGithubIntegrationError');
const PollForGithubIntegrationTimeout = StructuredError('PollForGithubIntegrationTimeout', 'Timed out waiting for GitHub integration. Aborting.');
export async function pollForGithubIntegration(apiClient, initialCount, timeoutMs = 600000 // 10 minutes
) {
    const started = Date.now();
    let delay = 2000; // Start with 2 seconds
    const maxDelay = 10000; // Cap at 10 seconds
    while (Date.now() - started < timeoutMs) {
        const resp = await apiClient.get('/cli/github/status', APIResponseSchema(GithubStatusDataSchema));
        if (!resp.success || !resp.data) {
            throw new PollForGithubIntegrationError();
        }
        const currentCount = resp.data.installations?.length ?? 0;
        if (currentCount > initialCount) {
            return {
                connected: true,
                identity: resp.data.identity,
                installations: resp.data.installations,
            };
        }
        await sleep(delay);
        delay = Math.min(delay * 1.5, maxDelay);
    }
    throw new PollForGithubIntegrationTimeout();
}
// Project linking
const GithubRepoSchema = z.object({
    id: z.number(),
    name: z.string(),
    fullName: z.string(),
    private: z.boolean(),
    defaultBranch: z.string(),
    integrationId: z.string(),
});
const GithubReposDataSchema = z.object({
    repos: z.array(GithubRepoSchema),
});
const GithubReposError = StructuredError('GithubReposError', 'Error fetching GitHub repositories');
export async function listGithubRepos(apiClient, integrationId) {
    let url = '/cli/github/repos';
    if (integrationId) {
        url += `?integrationId=${encodeURIComponent(integrationId)}`;
    }
    const resp = await apiClient.get(url, APIResponseSchema(GithubReposDataSchema));
    if (!resp.success || !resp.data) {
        throw new GithubReposError();
    }
    return resp.data.repos;
}
const ProjectLinkDataSchema = z.object({
    linked: z.boolean(),
});
const ProjectLinkError = StructuredError('ProjectLinkError', 'Error linking project to repository');
export async function linkProjectToRepo(apiClient, options) {
    const resp = await apiClient.post('/cli/github/link', options, APIResponseSchema(ProjectLinkDataSchema));
    if (!resp.success || !resp.data) {
        throw new ProjectLinkError();
    }
    return resp.data.linked;
}
const ProjectUnlinkDataSchema = z.object({
    unlinked: z.boolean(),
});
const ProjectUnlinkError = StructuredError('ProjectUnlinkError', 'Error unlinking project from repository');
export async function unlinkProjectFromRepo(apiClient, projectId) {
    const resp = await apiClient.delete(`/cli/github/unlink?projectId=${encodeURIComponent(projectId)}`, APIResponseSchema(ProjectUnlinkDataSchema));
    if (!resp.success || !resp.data) {
        throw new ProjectUnlinkError();
    }
    return resp.data.unlinked;
}
const ProjectGithubStatusSchema = z.object({
    linked: z.boolean(),
    repoFullName: z.string().optional(),
    branch: z.string().optional(),
    autoDeploy: z.boolean().optional(),
    previewDeploy: z.boolean().optional(),
    directory: z.string().optional(),
});
const ProjectGithubStatusError = StructuredError('ProjectGithubStatusError', 'Error fetching project GitHub status');
export async function getProjectGithubStatus(apiClient, projectId) {
    const resp = await apiClient.get(`/cli/github/project-status?projectId=${encodeURIComponent(projectId)}`, APIResponseSchema(ProjectGithubStatusSchema));
    if (!resp.success || !resp.data) {
        throw new ProjectGithubStatusError();
    }
    return resp.data;
}
// ─── GitHub Token ───
const GithubTokenDataSchema = z.object({
    token: z.string(),
    username: z.string(),
});
const GithubTokenError = StructuredError('GithubTokenError', 'Failed to retrieve GitHub token from Agentuity');
export async function getGithubToken(apiClient) {
    const resp = await apiClient.get('/cli/github/token', APIResponseSchema(GithubTokenDataSchema));
    if (!resp.success || !resp.data) {
        throw new GithubTokenError();
    }
    return resp.data;
}
const GithubRepoCheckDataSchema = z.object({
    available: z.boolean(),
    exists: z.boolean(),
    error: z.string().optional(),
});
const GithubRepoCheckError = StructuredError('GithubRepoCheckError', 'Error checking GitHub repository availability');
export async function checkGithubRepo(apiClient, params) {
    const resp = await apiClient.get(`/cli/github/repo/check?owner=${encodeURIComponent(params.owner)}&name=${encodeURIComponent(params.name)}`, APIResponseSchema(GithubRepoCheckDataSchema));
    if (!resp.success || !resp.data) {
        throw new GithubRepoCheckError();
    }
    return resp.data;
}
// Repo creation
const GithubRepoCreateDataSchema = z.object({
    url: z.string(),
    cloneUrl: z.string(),
    fullName: z.string(),
    private: z.boolean(),
    created: z.boolean(),
});
const GithubRepoCreateError = StructuredError('GithubRepoCreateError', 'Error creating GitHub repository');
export async function createGithubRepo(apiClient, params) {
    const resp = await apiClient.post('/cli/github/repo', params, APIResponseSchema(GithubRepoCreateDataSchema));
    if (!resp.success || !resp.data) {
        throw new GithubRepoCreateError();
    }
    return resp.data;
}
// ─── Bot Identity ───
const GithubBotIdentityDataSchema = z.object({
    name: z.string(),
    email: z.string(),
});
const GithubBotIdentityError = StructuredError('GithubBotIdentityError', 'Error fetching GitHub App bot identity');
export async function getGithubBotIdentity(apiClient) {
    const resp = await apiClient.get('/cli/github/bot-identity', APIResponseSchema(GithubBotIdentityDataSchema));
    if (!resp.success || !resp.data) {
        throw new GithubBotIdentityError();
    }
    return resp.data;
}
//# sourceMappingURL=api.js.map