import { Resource } from "../resource.js";
import { logger } from "../util/logger.js";
import { SentryApi } from "./api.js";
/**
 * Create and manage Sentry projects
 *
 * @example
 * // Create a basic Sentry project:
 * const project = await Project("my-project", {
 *   name: "My Project",
 *   team: "my-team",
 *   organization: "my-org"
 * });
 *
 * @example
 * // Create a project for a specific platform:
 * const project = await Project("js-project", {
 *   name: "JavaScript Project",
 *   team: "my-team",
 *   organization: "my-org",
 *   platform: "javascript"
 * });
 *
 * @example
 * // Create a project with a custom slug and disabled default rules:
 * const project = await Project("custom-project", {
 *   name: "Custom Project",
 *   team: "my-team",
 *   organization: "my-org",
 *   slug: "custom-project-slug",
 *   defaultRules: false
 * });
 *
 * @example
 * // Create or adopt an existing project with the same slug:
 * const project = await Project("existing-project", {
 *   name: "Existing Project",
 *   team: "my-team",
 *   organization: "my-org",
 *   adopt: true
 * });
 */
export const Project = Resource("sentry::Project", async function (id, props) {
    const api = new SentryApi({ authToken: props.authToken });
    // it's possible that `this.output.name` is undefined because a previous version
    // of alchemy had a bug where it didn't set the name on the output
    // so, we try to find the key by ID and use the name from the API response
    const lookupName = async () => {
        if (!this.output) {
            return undefined;
        }
        else if (this.output.name) {
            return this.output.name;
        }
        const name = await getProjectName(api, props.organization, this.output.id);
        if (name) {
            this.output.name = name;
        }
        return name;
    };
    const projectName = props.name ?? (await lookupName()) ?? this.scope.createPhysicalName(id);
    if (this.phase === "update" && this.output.name !== projectName) {
        await api.put(`/projects/${props.organization}/${this.output.slug || this.output.id}/`, {
            name: projectName,
        });
    }
    if (this.phase === "delete") {
        try {
            if (this.output?.id) {
                const response = await api.delete(`/projects/${props.organization}/${this.output.slug || this.output.id}/`);
                if (!response.ok && response.status !== 404) {
                    logger.error("Error deleting project:", response.statusText);
                }
            }
        }
        catch (error) {
            logger.error("Error deleting project:", error);
        }
        return this.destroy();
    }
    else {
        try {
            let response;
            if (this.phase === "update" && this.output?.id) {
                response = await api.put(`/projects/${props.organization}/${this.output.slug || this.output.id}/`, props);
            }
            else {
                try {
                    response = await api.post(`/teams/${props.organization}/${props.team}/projects/`, props);
                }
                catch (error) {
                    // Check if this is a "project already exists" error and adopt is enabled
                    if ((props.adopt ?? this.scope.adopt) &&
                        error instanceof Error &&
                        error.message.includes("already exists")) {
                        logger.log(`Project '${props.slug || projectName}' already exists, adopting it`);
                        // Find the existing project by slug
                        const existingProject = await findProjectBySlug(api, props.organization, props.slug || projectName);
                        if (!existingProject) {
                            throw new Error(`Failed to find existing project '${props.slug || projectName}' for adoption`);
                        }
                        response = await api.get(`/projects/${props.organization}/${existingProject.slug}/`);
                    }
                    else {
                        throw error;
                    }
                }
            }
            if (!response.ok) {
                throw new Error(`API error: ${await response.text()}`);
            }
            const data = (await response.json());
            return {
                ...props,
                id: data.id,
                name: projectName,
                team: data.team,
                teams: data.teams,
                isBookmarked: data.isBookmarked,
                isMember: data.isMember,
                access: data.access,
                hasAccess: data.hasAccess,
                dateCreated: data.dateCreated,
                environments: data.environments,
                eventProcessing: data.eventProcessing,
                features: data.features,
                firstEvent: data.firstEvent,
                firstTransactionEvent: data.firstTransactionEvent,
                hasSessions: data.hasSessions,
                hasProfiles: data.hasProfiles,
                hasReplays: data.hasReplays,
                hasFlags: data.hasFlags,
                hasMonitors: data.hasMonitors,
                hasFeedbacks: data.hasFeedbacks,
                hasNewFeedbacks: data.hasNewFeedbacks,
                hasMinifiedStackTrace: data.hasMinifiedStackTrace,
                hasInsightsHttp: data.hasInsightsHttp,
                hasInsightsDb: data.hasInsightsDb,
                hasInsightsAssets: data.hasInsightsAssets,
                hasInsightsAppStart: data.hasInsightsAppStart,
                hasInsightsScreenLoad: data.hasInsightsScreenLoad,
                hasInsightsVitals: data.hasInsightsVitals,
                hasInsightsCaches: data.hasInsightsCaches,
                hasInsightsQueues: data.hasInsightsQueues,
                hasInsightsLlmMonitoring: data.hasInsightsLlmMonitoring,
                platforms: data.platforms,
                latestRelease: data.latestRelease,
                hasUserReports: data.hasUserReports,
                latestDeploys: data.latestDeploys,
            };
        }
        catch (error) {
            logger.error("Error creating/updating project:", error);
            throw error;
        }
    }
});
/**
 * Find a project by slug
 */
async function findProjectBySlug(api, organization, slug) {
    const response = await api.get(`/projects/${organization}`);
    if (!response.ok) {
        throw new Error(`API error: ${response.statusText}`);
    }
    const projects = (await response.json());
    const project = projects.find((p) => p.slug === slug);
    return project ? { id: project.id, slug: project.slug } : null;
}
async function getProjectName(api, organization, slug) {
    const response = await api.get(`/projects/${organization}/${slug}/`);
    if (!response.ok) {
        throw new Error(`API error: ${response.statusText}`);
    }
    return (await response.json()).name;
}
//# sourceMappingURL=project.js.map