import { Resource, ResourceKind } from "../resource.js";
import { logger } from "../util/logger.js";
import { CloudflareApiError, handleApiError } from "./api-error.js";
import { createCloudflareApi, } from "./api.js";
export function isVectorizeIndex(resource) {
    return resource?.[ResourceKind] === "cloudflare::VectorizeIndex";
}
/**
 * Creates and manages Cloudflare Vectorize Indexes.
 *
 * Vectorize is Cloudflare's vector database that enables vector search within Cloudflare Workers.
 *
 * @example
 * // Create a basic vector index for text embeddings
 * const basicIndex = await VectorizeIndex("text-embeddings", {
 *   name: "text-embeddings",
 *   config: {
 *     dimensions: 768,
 *     metric: "cosine"
 *   }
 * });
 *
 * @example
 * // Create a vector index with a description
 * const descIndex = await VectorizeIndex("image-embeddings", {
 *   name: "image-embeddings",
 *   description: "Vector index for image embeddings using CLIP model",
 *   config: {
 *     dimensions: 512,
 *     metric: "cosine"
 *   }
 * });
 *
 * @example
 * // Adopt an existing index if it already exists instead of failing
 * const existingIndex = await VectorizeIndex("existing-index", {
 *   name: "existing-index",
 *   adopt: true,
 *   config: {
 *     dimensions: 1024,
 *     metric: "euclidean"
 *   }
 * });
 *
 * @see https://developers.cloudflare.com/vectorize/
 */
export const VectorizeIndex = Resource("cloudflare::VectorizeIndex", async function (id, props) {
    const api = await createCloudflareApi(props);
    const indexName = props.name ?? this.output?.name ?? this.scope.createPhysicalName(id);
    if (this.phase === "delete") {
        logger.log("Deleting Vectorize index:", indexName);
        if (props.delete !== false) {
            // Delete Vectorize index
            await deleteIndex(api, indexName);
        }
        // Return void (a deleted index has no content)
        return this.destroy();
    }
    let indexData;
    if (this.phase === "create") {
        logger.log("Creating Vectorize index:", indexName);
        try {
            indexData = await createIndex(api, indexName, {
                ...props,
                name: indexName,
            });
        }
        catch (error) {
            // Check if this is a "index already exists" error and adopt is enabled
            if ((props.adopt ?? this.scope.adopt) &&
                error instanceof CloudflareApiError &&
                error.message.includes("vectorize.index.duplicate_name")) {
                logger.log(`Index ${indexName} already exists, adopting it`);
                // Find the existing index
                indexData = await getIndex(api, indexName);
            }
            else {
                // Re-throw the error if adopt is false or it's not a "index already exists" error
                throw error;
            }
        }
    }
    else {
        if (this.output.name !== indexName) {
            return this.replace();
        }
        if (props.delete !== this.props.delete) {
            // Only allow changing the delete property
            if (!this.quiet) {
                logger.warn(`Attempted to update Vectorize index ${indexName} but only the delete property can be changed.`);
            }
            return {
                ...this.output,
                delete: props.delete,
            };
        }
        // Check if this is a no-op update
        if (props.name === this.props.name &&
            props.description === this.props.description &&
            props.dimensions === this.props.dimensions &&
            props.metric === this.props.metric) {
            if (!this.quiet) {
                logger.warn(`Attempted to update Vectorize index ${indexName} but it was a no-op.`);
            }
            return this.output;
        }
        // Update operation is not supported by Vectorize API
        throw new Error("Updating Vectorize indexes is not supported by the Cloudflare API. " +
            "To change an index, delete it and create a new one with the desired configuration.");
    }
    return {
        type: "vectorize",
        id: indexName,
        name: indexName,
        description: props.description,
        dimensions: indexData.result.config.dimensions,
        metric: indexData.result.config.metric,
        accountId: api.accountId,
        createdAt: indexData.result.created_on
            ? new Date(indexData.result.created_on).getTime()
            : undefined,
    };
});
/**
 * Create a new Vectorize index
 */
export async function createIndex(api, indexName, props) {
    // Create new Vectorize index
    const createPayload = {
        name: indexName,
        config: {
            dimensions: props.dimensions,
            metric: props.metric,
        },
    };
    if (props.description) {
        createPayload.description = props.description;
    }
    const createResponse = await api.post(`/accounts/${api.accountId}/vectorize/v2/indexes`, createPayload);
    if (!createResponse.ok) {
        return await handleApiError(createResponse, "creating", "Vectorize index", indexName);
    }
    return (await createResponse.json());
}
/**
 * Get a Vectorize index
 */
export async function getIndex(api, indexName) {
    const response = await api.get(`/accounts/${api.accountId}/vectorize/v2/indexes/${indexName}`);
    if (!response.ok) {
        return await handleApiError(response, "getting", "Vectorize index", indexName);
    }
    return (await response.json());
}
/**
 * Delete a Vectorize index
 */
export async function deleteIndex(api, indexName) {
    // Delete Vectorize index
    const deleteResponse = await api.delete(`/accounts/${api.accountId}/vectorize/v2/indexes/${indexName}`);
    if (!deleteResponse.ok &&
        // not 404 (Not Found) or 410 (Gone)
        deleteResponse.status !== 404 &&
        deleteResponse.status !== 410) {
        const errorData = await deleteResponse.json().catch(() => ({
            errors: [{ message: deleteResponse.statusText }],
        }));
        throw new CloudflareApiError(`Error deleting Vectorize index '${indexName}': ${errorData.errors?.[0]?.message || deleteResponse.statusText}`, deleteResponse);
    }
}
/**
 * List all Vectorize indexes in an account
 */
export async function listIndexes(api) {
    const response = await api.get(`/accounts/${api.accountId}/vectorize/v2/indexes`);
    if (!response.ok) {
        throw new CloudflareApiError(`Failed to list indexes: ${response.statusText}`, response);
    }
    const data = (await response.json());
    if (!data.success) {
        const errorMessage = data.errors?.[0]?.message || "Unknown error";
        throw new Error(`Failed to list indexes: ${errorMessage}`);
    }
    // Transform API response
    return (data.result || []).map((index) => ({
        name: index.name,
        description: index.description,
    }));
}
/**
 * Update a Vectorize index
 *
 * Note: The Cloudflare Vectorize API does not support updating indexes.
 * This function will always throw an error.
 */
export async function updateIndex(_api, _indexName, _props) {
    throw new Error("Updating Vectorize indexes is not supported by the Cloudflare API. To change an index, delete it and create a new one.");
}
//# sourceMappingURL=vectorize-index.js.map