export const MAX_TERMINAL_SESSION_TIMEOUT_SECONDS = 8 * 60 * 60;

export function getTerminalSessionTimeout() {
    return MAX_TERMINAL_SESSION_TIMEOUT_SECONDS;
}

export function extractTimeout(commandString) {
    const timeoutMatch = commandString.match(/timeout (\d+)/);
    return timeoutMatch ? parseInt(timeoutMatch[1], 10) : null;
}

function normalizeShellArgument(argument) {
    if (!argument) {
        return argument;
    }

    return argument
        .replace(/'([^']*)'/g, '$1')
        .replace(/"([^"]*)"/g, '$1');
}

export function extractSshArgs(commandString) {
    const sshCommandMatch = commandString.match(/ssh (.+?) 'bash -se'/);
    if (!sshCommandMatch) return [];

    const argsString = sshCommandMatch[1];
    let sshArgs = [];

    let current = '';
    let inQuotes = false;
    let quoteChar = '';
    let i = 0;

    while (i < argsString.length) {
        const char = argsString[i];

        if (!inQuotes && (char === '"' || char === "'")) {
            inQuotes = true;
            quoteChar = char;
            current += char;
        } else if (inQuotes && char === quoteChar) {
            inQuotes = false;
            current += char;
            quoteChar = '';
        } else if (!inQuotes && char === ' ') {
            if (current.trim()) {
                sshArgs.push(current.trim());
                current = '';
            }
        } else {
            current += char;
        }
        i++;
    }

    if (current.trim()) {
        sshArgs.push(current.trim());
    }

    sshArgs = sshArgs.map((arg) => normalizeShellArgument(arg));
    sshArgs = sshArgs.map(arg => arg === 'RequestTTY=no' ? 'RequestTTY=yes' : arg);

    if (!sshArgs.includes('RequestTTY=yes') && !sshArgs.some(arg => arg.includes('RequestTTY='))) {
        sshArgs.push('-o', 'RequestTTY=yes');
    }

    return sshArgs;
}

export function extractHereDocContent(commandString) {
    const delimiterMatch = commandString.match(/<< (\S+)/);
    const delimiter = delimiterMatch ? delimiterMatch[1] : null;
    const escapedDelimiter = delimiter?.slice(1).trim().replace(/[/\-\\^$*+?.()|[\]{}]/g, '\\$&');

    if (!escapedDelimiter) {
        return '';
    }

    const hereDocRegex = new RegExp(`<< \\\\${escapedDelimiter}([\\s\\S\\.]*?)${escapedDelimiter}`);
    const hereDocMatch = commandString.match(hereDocRegex);
    return hereDocMatch ? hereDocMatch[1] : '';
}

export function normalizeHostForAuthorization(host) {
    if (!host) {
        return null;
    }

    let normalizedHost = host.trim();

    while (
        normalizedHost.length >= 2 &&
        ((normalizedHost.startsWith("'") && normalizedHost.endsWith("'")) ||
            (normalizedHost.startsWith('"') && normalizedHost.endsWith('"')))
    ) {
        normalizedHost = normalizedHost.slice(1, -1).trim();
    }

    if (normalizedHost.startsWith('[') && normalizedHost.endsWith(']')) {
        normalizedHost = normalizedHost.slice(1, -1);
    }

    return normalizedHost.toLowerCase();
}

export function extractTargetHost(sshArgs) {
    const userAtHost = sshArgs.find(arg => {
        if (arg.includes('storage/app/ssh/keys/')) {
            return false;
        }

        return /^[^@]+@[^@]+$/.test(arg);
    });

    if (!userAtHost) {
        return null;
    }

    const atIndex = userAtHost.indexOf('@');
    return normalizeHostForAuthorization(userAtHost.slice(atIndex + 1));
}

export function isAuthorizedTargetHost(targetHost, authorizedHosts = []) {
    const normalizedTargetHost = normalizeHostForAuthorization(targetHost);

    if (!normalizedTargetHost) {
        return false;
    }

    return authorizedHosts
        .map(host => normalizeHostForAuthorization(host))
        .includes(normalizedTargetHost);
}
