import { cwd } from 'node:process';
import { resolve } from 'node:path';
import { error } from '../model/error.js';
import { getApiUrl } from '../model/url.js';

export const downloadApplication = async ({ console, profile, fs, fetch, application }) => {
    const serverUrl = profile?.server_url;
    if (!serverUrl) {
        const err = new Error('Cannot download application. Server URL is missing.');
        throw err;
    }

    const token = profile?.token?.access_token;
    if (!token) {
        const err = new Error('Cannot download application. Access token is missing.');
        throw err;
    }

    if (!application) {
        const err = new Error('Cannot download application. Application parameter is missing.');
        throw err;
    }

    const apiUrl = getApiUrl(serverUrl, `./v1/applications/${application}/download`);

    console.debug(`Downloading application from: ${String(apiUrl)}`);
    const res = await fetch(apiUrl, {
        method: 'GET',
        headers: {
            'Authorization': 'Bearer ' + token
        }
    });
    if (res.status !== 200) {
        throw error(
            `Cannot download application. Server error: ${res.status} ${res.statusText} ` +
      await res.text(),
            res.status
        );
    }
    const data = await res.bytes();
    const savedFilePath = await saveDownloadedResponse({fs, res, data, outputDir: cwd()});
    return 'Application downloaded and saved to: ' + savedFilePath;
};

const saveDownloadedResponse = async ({fs, res, data, outputDir}) => {
    const failParseResp = 'Failed to parse download application response ';
    const contentDisposition = res.headers.get('Content-Disposition');
    if (!contentDisposition) {
        throw error(failParseResp + 'Content-Disposition header is missing');
    }
    const filenameMatch = contentDisposition.match(/filename="([^"]+)"/);
    if (!filenameMatch || !filenameMatch[1]) {
        throw new Error(failParseResp + 'filename is missing');
    }
    const filename = filenameMatch[1];
    const filePath = resolve(outputDir, filename);

    await fs.writeFile(filePath, data);
    return filePath;
};
