import { spawn } from 'node:child_process';
import { mkdir, readFile, rm, stat } from 'node:fs/promises';
import { tmpdir } from 'node:os';
import { basename, join, resolve } from 'node:path';
import process from 'node:process';
import { log } from '@clack/prompts';
import { createSupabaseClient, findSavedKey, getConfig, verifyUser } from '../utils';
async function zipDirectory(projectDir, outputPath) {
    return new Promise((resolvePromise, reject) => {
        const args = ['-rq', outputPath, '.'];
        const child = spawn('zip', args, { cwd: projectDir, stdio: 'inherit' });
        child.on('error', (error) => {
            if (error.code === 'ENOENT') {
                reject(new Error('zip command not found. Please install zip utility.'));
            }
            else {
                reject(error);
            }
        });
        child.on('close', (code) => {
            if (code === 0) {
                resolvePromise();
            }
            else {
                reject(new Error(`zip process exited with code ${code}`));
            }
        });
    });
}
export async function requestBuildInternal(appId, options, silent = false) {
    try {
        options.apikey = options.apikey || findSavedKey(silent);
        const config = await getConfig();
        appId = appId || config?.config.appId;
        if (!appId) {
            throw new Error('Missing argument, you need to provide a appId, or be in a capacitor project');
        }
        const projectDir = resolve(options.path || process.cwd());
        const supabase = await createSupabaseClient(options.apikey, options.supaHost, options.supaAnon);
        await verifyUser(supabase, options.apikey, ['write', 'all']);
        if (!silent) {
            log.info(`Requesting native build for ${appId}`);
            log.info(`Platform: ${options.lane}`);
            log.info(`Project: ${projectDir}`);
        }
        // Prepare request payload for Capgo backend
        const requestPayload = {
            app_id: appId,
            platform: options.lane,
        };
        // Add build mode if specified
        if (options.buildMode) {
            requestPayload.build_mode = options.buildMode;
        }
        // Add credentials if provided
        if (options.credentials) {
            requestPayload.credentials = options.credentials;
        }
        // Request build from Capgo backend (POST /build/request)
        if (!silent)
            log.info('Requesting build from Capgo...');
        const host = options.supaHost || 'https://api.capgo.app';
        const response = await fetch(`${host}/build/request`, {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
                'authorization': options.apikey,
            },
            body: JSON.stringify(requestPayload),
        });
        if (!response.ok) {
            const errorText = await response.text();
            throw new Error(`Failed to request build: ${response.status} - ${errorText}`);
        }
        const buildRequest = await response.json();
        if (!silent) {
            log.success(`Build job created: ${buildRequest.job_id}`);
            log.info(`Status: ${buildRequest.status}`);
        }
        // Create temporary directory for zip
        const tempDir = join(tmpdir(), `capgo-build-${Date.now()}`);
        await mkdir(tempDir, { recursive: true });
        const zipPath = join(tempDir, `${basename(projectDir)}.zip`);
        try {
            // Zip the project directory
            if (!silent)
                log.info(`Zipping project from ${projectDir}...`);
            await zipDirectory(projectDir, zipPath);
            const zipStats = await stat(zipPath);
            const sizeMB = (zipStats.size / 1024 / 1024).toFixed(2);
            if (!silent)
                log.success(`Created zip: ${zipPath} (${sizeMB} MB)`);
            // Upload to presigned R2 URL
            if (!silent)
                log.info('Uploading to builder...');
            const fileBuffer = await readFile(zipPath);
            const uploadResponse = await fetch(buildRequest.upload_url, {
                method: 'PUT',
                headers: {
                    'Content-Type': 'application/zip',
                    'Content-Length': String(zipStats.size),
                },
                body: fileBuffer,
            });
            if (!uploadResponse.ok) {
                const errorText = await uploadResponse.text();
                throw new Error(`Upload failed: ${uploadResponse.status} - ${errorText}`);
            }
            if (!silent)
                log.success('Upload complete!');
            // Start the build job via Capgo backend
            if (!silent)
                log.info('Starting build job...');
            const startResponse = await fetch(`${host}/build/start/${buildRequest.build_request_id}`, {
                method: 'POST',
                headers: {
                    'authorization': options.apikey,
                },
            });
            if (!startResponse.ok) {
                const errorText = await startResponse.text();
                throw new Error(`Failed to start build: ${startResponse.status} - ${errorText}`);
            }
            const startResult = await startResponse.json();
            if (!silent) {
                log.success('Build started successfully!');
                log.info(`Job ID: ${buildRequest.job_id}`);
                log.info('You can monitor the build in the Capgo dashboard.');
            }
            return {
                success: true,
                jobId: buildRequest.job_id,
                uploadUrl: buildRequest.upload_url,
                status: startResult.status || buildRequest.status,
            };
        }
        finally {
            // Clean up temp directory
            await rm(tempDir, { recursive: true, force: true });
        }
    }
    catch (error) {
        const errorMessage = error instanceof Error ? error.message : String(error);
        if (!silent)
            log.error(errorMessage);
        return {
            success: false,
            error: errorMessage,
        };
    }
}
export async function requestBuildCommand(appId, options) {
    const result = await requestBuildInternal(appId, options, false);
    if (!result.success) {
        process.exit(1);
    }
}
//# sourceMappingURL=request.js.map