import { readdir, readFile } from "node:fs/promises";
import * as path from "node:path";
import { getBucketeerUrlFromSuperblocksUrl } from "@superblocksteam/util";
import { getErrorMeta } from "../util/logger.js";
import { getScopedToken } from "./util/scoped-token-utils.js";
/**
 * Uploads all context files from the context folder to Bucketeer
 * Reads all files from .superblocks/context/{userId}/ and uploads them
 * Dynamically detects MIME types for any file type
 */
export async function uploadContextToBucketeer({ applicationId, commitId, branchName, appRootDirPath, userId, useServerUpload = false, superblocksBaseUrl, logger, jwt, }) {
    // Get the context directory path for this userId
    const contextDir = path.join(appRootDirPath, ".superblocks", "context", userId);
    // Read all files in the context directory
    let contextFiles;
    try {
        const entries = await readdir(contextDir, { withFileTypes: true });
        // Filter to only files (exclude directories) and get their names
        contextFiles = entries
            .filter((entry) => entry.isFile())
            .map((entry) => entry.name);
    }
    catch (err) {
        if (err.code === "ENOENT") {
            // Context directory doesn't exist - this is fine, just return
            logger.info(`[uploadContextToBucketeer] No context directory found for userId=${userId}, skipping upload`);
            return;
        }
        throw err;
    }
    if (contextFiles.length === 0) {
        logger.info(`[uploadContextToBucketeer] No context files found for userId=${userId}, skipping upload`);
        return;
    }
    const contextFileData = [];
    const uploadedFiles = [];
    for (const fileName of contextFiles) {
        const filePath = path.join(contextDir, fileName);
        try {
            // Read file as buffer to preserve binary content
            const fileBuffer = await readFile(filePath);
            // Convert Buffer to Uint8Array for Blob
            // Content-Type is optional - server can infer from filename
            contextFileData.push({ data: fileBuffer, fileName });
            uploadedFiles.push(fileName);
        }
        catch (err) {
            logger.warn(`[uploadContextToBucketeer] Failed to read context file ${fileName}, skipping`, getErrorMeta(err));
            // Continue with other files even if one fails
        }
    }
    if (uploadedFiles.length === 0) {
        logger.warn(`[uploadContextToBucketeer] No files were successfully read for upload`);
        return;
    }
    const buildFormData = () => {
        const formData = new FormData();
        for (const contextFile of contextFileData) {
            formData.append("context", new Blob([new Uint8Array(contextFile.data)]), contextFile.fileName);
        }
        return formData;
    };
    const uploadViaServer = async () => {
        const url = new URL(`${superblocksBaseUrl}/api/v1/files/upload`);
        url.searchParams.set("scopeType", "app");
        url.searchParams.set("purpose", "context");
        url.searchParams.set("applicationId", applicationId);
        url.searchParams.set("branchName", branchName);
        url.searchParams.set("commitId", commitId);
        const response = await fetch(url.toString(), {
            method: "POST",
            body: buildFormData(),
            headers: {
                Authorization: `Bearer ${jwt}`,
            },
        });
        if (!response.ok) {
            const errorText = await response
                .text()
                .catch(() => "Unable to read error response");
            throw new Error(`Server context upload failed: status=${response.status}, error=${errorText}`);
        }
    };
    const uploadViaBucketeer = async () => {
        let scopedToken;
        try {
            scopedToken = await getScopedToken({
                applicationId,
                superblocksBaseUrl,
                jwt,
            });
        }
        catch (error) {
            logger.error("[uploadContextToBucketeer] Failed to get scoped token", getErrorMeta(error));
            throw error;
        }
        // Get Bucketeer URL from Superblocks base URL
        const bucketeerUrl = getBucketeerUrlFromSuperblocksUrl(superblocksBaseUrl);
        // Upload to Bucketeer using the branch-aware context endpoint
        const url = `${bucketeerUrl}/applications/${applicationId}/branches/${encodeURIComponent(branchName)}/commits/${encodeURIComponent(commitId)}/context`;
        const response = await fetch(url, {
            method: "POST",
            body: buildFormData(),
            headers: {
                Authorization: `Bearer ${scopedToken}`,
                // Content-Type will be set automatically by fetch with boundary
            },
        });
        if (!response.ok) {
            const errorText = await response
                .text()
                .catch(() => "Unable to read error response");
            logger.error(`[uploadContextToBucketeer] Upload failed: status=${response.status}, statusText=${response.statusText}, error=${errorText} for applicationId=${applicationId}, commitId=${commitId}`);
            throw new Error(`Context upload failed: ${response.statusText}`);
        }
    };
    try {
        if (useServerUpload) {
            try {
                await uploadViaServer();
            }
            catch (error) {
                logger.warn("[uploadContextToBucketeer] Server context upload failed, falling back to Bucketeer", getErrorMeta(error));
                await uploadViaBucketeer();
            }
        }
        else {
            await uploadViaBucketeer();
        }
        logger.info(`[uploadContextToBucketeer] Successfully uploaded ${uploadedFiles.length} context file(s) (${uploadedFiles.join(", ")}) for applicationId=${applicationId}, commitId=${commitId}`);
    }
    catch (error) {
        logger.error("[uploadContextToBucketeer] Failed to upload context", getErrorMeta(error));
        throw error;
    }
}
//# sourceMappingURL=context-upload.js.map