// Shared Ivanti / RiskSense API helpers
// Centralizes HTTP calls so ivantiWorkflows.js, ivantiFindings.js, and
// ivantiFpWorkflow.js all use the same implementation.

const https = require('https');

const IVANTI_URL_BASE = 'https://platform4.risksense.com/api/v1';

// ---------------------------------------------------------------------------
// JSON POST — used for search, workflow creation, etc.
// ---------------------------------------------------------------------------
function ivantiPost(urlPath, body, apiKey, skipTls) {
    const bodyStr = JSON.stringify(body);
    const fullUrl = new URL(IVANTI_URL_BASE + urlPath);

    return new Promise((resolve, reject) => {
        const options = {
            hostname: fullUrl.hostname,
            path: fullUrl.pathname + fullUrl.search,
            method: 'POST',
            headers: {
                'accept': '*/*',
                'content-type': 'application/json',
                'x-api-key': apiKey,
                'x-http-client-type': 'browser',
                'content-length': Buffer.byteLength(bodyStr)
            },
            rejectUnauthorized: !skipTls,
            timeout: 15000
        };

        const req = https.request(options, (res) => {
            let data = '';
            res.on('data', (chunk) => { data += chunk; });
            res.on('end', () => resolve({ status: res.statusCode, body: data }));
        });

        req.on('timeout', () => req.destroy(new Error('Request timed out')));
        req.on('error', reject);
        req.write(bodyStr);
        req.end();
    });
}

// ---------------------------------------------------------------------------
// Multipart POST — used for file attachment uploads.
// Constructs multipart/form-data manually using Node's https module.
// ---------------------------------------------------------------------------
function ivantiMultipartPost(urlPath, fileBuffer, fileName, apiKey, skipTls) {
    const boundary = '----IvantiUpload' + Date.now().toString(36) + Math.random().toString(36).slice(2);
    const fullUrl = new URL(IVANTI_URL_BASE + urlPath);

    // Build multipart body
    const preamble = Buffer.from(
        `--${boundary}\r\n` +
        `Content-Disposition: form-data; name="file"; filename="${fileName}"\r\n` +
        `Content-Type: application/octet-stream\r\n\r\n`
    );
    const epilogue = Buffer.from(`\r\n--${boundary}--\r\n`);
    const bodyBuffer = Buffer.concat([preamble, fileBuffer, epilogue]);

    return new Promise((resolve, reject) => {
        const options = {
            hostname: fullUrl.hostname,
            path: fullUrl.pathname + fullUrl.search,
            method: 'POST',
            headers: {
                'accept': '*/*',
                'content-type': `multipart/form-data; boundary=${boundary}`,
                'x-api-key': apiKey,
                'x-http-client-type': 'browser',
                'content-length': bodyBuffer.length
            },
            rejectUnauthorized: !skipTls,
            timeout: 30000
        };

        const req = https.request(options, (res) => {
            let data = '';
            res.on('data', (chunk) => { data += chunk; });
            res.on('end', () => resolve({ status: res.statusCode, body: data }));
        });

        req.on('timeout', () => req.destroy(new Error('Request timed out')));
        req.on('error', reject);
        req.write(bodyBuffer);
        req.end();
    });
}

// ---------------------------------------------------------------------------
// Multipart form POST — used for endpoints that accept mixed form fields + files.
// fields: array of { name, value } for text form fields
// files:  array of { name, buffer, filename } for file uploads
// ---------------------------------------------------------------------------
function ivantiFormPost(urlPath, fields, files, apiKey, skipTls) {
    const boundary = '----IvantiForm' + Date.now().toString(36) + Math.random().toString(36).slice(2);
    const fullUrl = new URL(IVANTI_URL_BASE + urlPath);

    const parts = [];

    // Text fields
    for (const { name, value } of fields) {
        parts.push(Buffer.from(
            `--${boundary}\r\n` +
            `Content-Disposition: form-data; name="${name}"\r\n\r\n` +
            `${value}\r\n`
        ));
    }

    // File fields
    for (const { name, buffer, filename, contentType } of files) {
        parts.push(Buffer.from(
            `--${boundary}\r\n` +
            `Content-Disposition: form-data; name="${name}"; filename="${filename}"\r\n` +
            `Content-Type: ${contentType || 'application/octet-stream'}\r\n\r\n`
        ));
        parts.push(buffer);
        parts.push(Buffer.from('\r\n'));
    }

    parts.push(Buffer.from(`--${boundary}--\r\n`));
    const bodyBuffer = Buffer.concat(parts);

    return new Promise((resolve, reject) => {
        const options = {
            hostname: fullUrl.hostname,
            path: fullUrl.pathname + fullUrl.search,
            method: 'POST',
            headers: {
                'accept': '*/*',
                'content-type': `multipart/form-data; boundary=${boundary}`,
                'x-api-key': apiKey,
                'x-http-client-type': 'browser',
                'content-length': bodyBuffer.length
            },
            rejectUnauthorized: !skipTls,
            timeout: 60000
        };

        const req = https.request(options, (res) => {
            let data = '';
            res.on('data', (chunk) => { data += chunk; });
            res.on('end', () => resolve({ status: res.statusCode, body: data }));
        });

        req.on('timeout', () => req.destroy(new Error('Request timed out')));
        req.on('error', reject);
        req.write(bodyBuffer);
        req.end();
    });
}

module.exports = { IVANTI_URL_BASE, ivantiPost, ivantiMultipartPost, ivantiFormPost };
