import { createServer } from 'node:http';
import open from 'open';

export const getCode = async ({
    console, profile, info, state, codeChallenge, serviceKey,
    redirectUri = 'http://localhost:8080/'
}) => {
    if (!state) {
        const err = new Error('Can not get token. State is missing');
        throw err;
    }
    if (serviceKey) {
        if (!serviceKey.uaa) {
            const err = new Error('Can not get token. Service key \'uaa\' property is missing');
            throw err;
        }
    } else {
        if (!profile) {
            const err = new Error('Can not get token. Profile is missing');
            throw err;
        }
        if (!info) {
            const err = new Error('Can not get token. Server info is missing');
            throw err;
        }
        if (!codeChallenge) {
            const err = new Error('Can not get token. Code challenge is missing');
            throw err;
        }
    }
    const serverPromise = new Promise((resolve, reject) => {
        console.debug('Starting new local server to listen on ' + redirectUri);
        const server = createServer((req, res) => {
            const url = new URL(req.url, redirectUri);
            if (url.searchParams.get('state') !== state) {
                const msg = 'State parameter does not match';
                console.debug(msg + `: expected ${state}, got ${url.searchParams.get('state')}`);

                res.statusCode = 400;
                res.setHeader('Content-Security-Policy', 'default-src none');
                res.end(msg);

                const err = new Error(msg);
                return reject(err);
            }
            const code = url.searchParams.get('code');
            console.debug(`Received authorization code: ${code}`);
            res.end([
                '<html>',
                '  <body>',
                '    <h2 style="color:green;">&#x2713; Login Successful!</h2>',
                '    <p>You can close this window and return to the work with afctl.</p>',
                '  </body>',
                '</html>'
            ].join('\n'));
            console.debug('Stopping the local server');
            server.close();
            return resolve(code);
        });
        server.on('error', err => reject(err));
        server.listen('8080');
    });
    // Open browser
    const issuer = serviceKey ? serviceKey.uaa.url : info.issuer;
    const issuerHasSchema = issuer.startsWith('http://') || issuer.startsWith('https://');
    const url = new URL(issuerHasSchema ? issuer : 'https://' + issuer);
    url.search = '';
    url.searchParams.set('response_type', 'code');
    url.searchParams.set('state', state);
    url.searchParams.set('redirect_uri', redirectUri);
    if (serviceKey) {
        // XSUAA
        url.pathname = '/oauth/authorize';
        url.searchParams.set('client_id', serviceKey.uaa.clientid);
        url.searchParams.set('login_hint', '{"origin":"sap.default"}');
    } else {
        // IAS
        url.pathname = '/oauth2/authorize';
        url.searchParams.set('client_id', info.client_id);
        url.searchParams.set('scope', 'openid');
        url.searchParams.set('code_challenge_method', 'S256');
        url.searchParams.set('access_type', 'offline');
        url.searchParams.set('code_challenge', codeChallenge);
        url.searchParams.set('app_tid', profile.apptid);
    }
    console.debug(`Opening browser with URL: ${url.toString()}`);
    await open(url.toString());
    return serverPromise;
};
