import { format } from 'util';
import { CodeBuilder } from '../../helpers/code-builder.js';
import { normalizeMimeType } from '../../../../utils.js';
import { addIndentation, buildUrlExpression, printUrlVariablesDeclarations, } from '../../helpers/code-helpers.js';
import { HTTPSnippet } from '../../index.js';
import { Lang } from '../../helpers/constants.js';
import { MediaTypes } from '../../../../../constants.js';
const handler = function (source, originalOptions, { target, client }) {
    const options = Object.assign({ indent: '  ' }, originalOptions);
    const { level = 0 } = options;
    const code = new CodeBuilder({
        indentation: options.indent,
        variablesPrefix: options.variablesPrefix,
        lang: Lang.PYTHON,
    });
    if (options.withComments) {
        addComments(code);
    }
    if (options.withImports) {
        code.push('import requests').blank();
    }
    let preserverOriginalAuthorizationHeader = false;
    let headers = source.allHeaders;
    if (source.securityOAuth2ExtraCalls?.length) {
        const oAuth2PrefixCode = new HTTPSnippet(source.securityOAuth2ExtraCalls?.[0]).convert(target, client, { ...options, withImports: false, withComments: false, variablesPrefix: 'oauth2_' });
        code.push(oAuth2PrefixCode);
        code.blank();
        headers = headers || {};
        headers.Authorization = `"Bearer " + oauth2_data["access_token"]`;
        preserverOriginalAuthorizationHeader = true;
    }
    printUrlVariablesDeclarations(source, code);
    // Set URL
    code.push(`${code.var('url').toLowerCase()} = %s`, buildUrlExpression(source, code)).blank();
    let qs;
    // Construct query string
    if (Object.keys(source.queryObj || {}).length) {
        const stringifiedQuery = jsObjectToPythonDict(source.queryObj, options.indent);
        qs = 'query = ' + stringifiedQuery; // TODO: handle inlineCharacterLimit: 25 as for stringifyQueryString
        code.push(qs).blank();
    }
    // Construct payload
    let payload;
    let dataStr;
    const normalizedMimeType = normalizeMimeType(source.postData?.mimeType);
    if (source.postData) {
        switch (normalizedMimeType) {
            case MediaTypes.URL_ENCODED:
                payload = source.postData.paramsObj
                    ? `${addIndentation(jsObjectToPythonDict(source.postData.paramsObj, options.indent), {
                        level: 0,
                        firstLine: false,
                    })}`
                    : source.postData.text;
                break;
            case MediaTypes.JSON:
                if (source.postData.jsonObj) {
                    payload = addIndentation(jsObjectToPythonDict(source.postData.jsonObj, options.indent), {
                        level: 0,
                        firstLine: false,
                    });
                }
                break;
            case MediaTypes.MULTIPART:
                const multipartData = [];
                if (source.postData.params) {
                    for (const param of source.postData.params) {
                        multipartData.push(`"${param.name}": "${param.value}"`);
                    }
                }
                if (multipartData.length) {
                    const formattedData = multipartData.map((entry) => `  ${entry}`).join(',\n');
                    dataStr = `data = {\n${formattedData}\n}`;
                }
                if (dataStr) {
                    code.push(dataStr).blank();
                }
                break;
            default:
                if (source.postData.text) {
                    payload = `'''\n${addIndentation(source.postData.text.trim(), {
                        level: 1,
                        indent: options.indent,
                        firstLine: true,
                    })}\n'''`;
                }
        }
    }
    if (payload) {
        code.push(`${code.var('payload').toLowerCase()} = %s`, payload).blank();
    }
    // Construct headers
    let header;
    const headerCount = Object.keys(headers).length;
    const formatHeader = (header, value) => {
        if (header === 'Authorization' && preserverOriginalAuthorizationHeader) {
            return value;
        }
        return `"${value}"`;
    };
    if (headerCount === 1) {
        for (header in headers) {
            // code.push('headers = { "%s": "%s" }', header, headers[header]).blank();
            code
                .push(`${code.var('headers').toLowerCase()} = {"${header}": ${formatHeader(header, headers[header])}}`)
                .blank();
        }
    }
    else if (headerCount > 1) {
        let count = 1;
        code.push(`${code.var('headers').toLowerCase()} = {`);
        for (header in headers) {
            if (count++ !== headerCount) {
                code.push(1, `"${header}": ${formatHeader(header, headers[header])},`);
            }
            else {
                code.push(1, `"${header}": ${formatHeader(header, headers[header])}`);
            }
        }
        code.push(0, '}').blank();
    }
    // Construct request
    const method = source.method.toLowerCase();
    let request = format(`${code.var('response').toLowerCase()} = requests.${method}(${code.var('url').toLowerCase()}`);
    if (normalizedMimeType === MediaTypes.MULTIPART && dataStr) {
        request += `, data=data`;
    }
    if (payload) {
        const dataType = normalizedMimeType === MediaTypes.JSON ? 'json' : 'data';
        request += `, ${dataType}=${code.var('payload').toLowerCase()}`;
    }
    if (headerCount > 0) {
        request += `, headers=${code.var('headers').toLowerCase()}`;
    }
    if (qs) {
        request += `, params=${code.var('query').toLowerCase()}`;
    }
    if (source.basicAuth) {
        request += `, auth=('${source.basicAuth.username}','${source.basicAuth.password}')`;
    }
    request += ')';
    code.push(request).blank();
    // Print response
    if (source.allResponseCodes?.includes('204')) {
        code
            .push(`if response.status_code == 204:`)
            .push(level + 1, 'print("success")')
            .push('else:')
            .push(level + 1, `${code.var('data').toLowerCase()} = ${code.var('response').toLowerCase()}.json()`)
            .push(level + 1, `print(${code.var('data').toLowerCase()})`);
    }
    else {
        code
            .push(`${code.var('data').toLowerCase()} = ${code.var('response').toLowerCase()}.json()`)
            .push(`print(${code.var('data').toLowerCase()})`);
    }
    return code.join();
};
export default handler;
function addComments(code) {
    code.push('"""');
    code.push('Requires python >= 3');
    code.blank();
    code.push('Requires module "requests" >= 2.25.1');
    code.push('See here for installation details:');
    code.push('  https://requests.readthedocs.io/');
    code.push('"""');
    code.blank();
}
function jsObjectToPythonDict(input, indent) {
    // TODO: add inlineCharacterLimit: 25 as for stringifyObject
    return JSON.stringify(input, function replacer(key, value) {
        if (key && typeof value === 'boolean') {
            if (value) {
                return '__REDOCLY_<True>__';
            }
            return '__REDOCLY_<False>__';
        }
        if (value === null) {
            return '__REDOCLY_<None>__';
        }
        return value;
    }, indent).replace(/"__REDOCLY_<(\w+)>__"/g, '$1');
}
//# sourceMappingURL=requests.js.map