// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.

import process from "process";

const fs = require("fs");
import path from "path";
// *** Main ***
main();

/**
 * Print usage and exit
 */
function usage() {
    console.log("psql.js [describe|sql] [table|file] [--format=json|table]")
    process.exit(1);
}

/**
 * Read a file and return content as string.
 * If file doesn't exists, process will exit in error
 * @param filename
 * @returns {Promise<string>}
 */
async function getFile(filename) {
    let fullFileName = '';
    if (!path.isAbsolute(filename)) {
        fullFileName = [
            process.env.OPS_PWD,
            filename
        ].join(path.sep);
    } else {
        fullFileName = filename;
    }

    const file = Bun.file(fullFileName);
    if (!await file.exists()) {
        throw Error(`File ${fullFileName} doesn't exists`);
    }
    return await file.text();
}

async function main() {

    const auth = process.env.AUTHB64
    const psqlAddr = `${process.env.APIHOST}/api/v1/web/whisk-system/nuv/psql`;

    // parse command line
    let command, param, format;
    command = String(Bun.argv[2]);
    if (Bun.argv[3] && Bun.argv[3].length > 0) {
        param = String(Bun.argv[3]);
        param = param.replace(/(\r\n|\n|\r)/gm, "");
    }
    format = (Bun.argv.length === 5) ? Bun.argv[4] : Bun.argv[3];
    if (!format) {
        format = 'json';
    }

    if (['json', 'table'].indexOf(format) === -1) {
        console.log(`Unsupported output format ${format}`);
        usage();
    }

    // build the command for system action
    const cmds = []

    if ('describe' === command) {
        let userSchema = process.env.OPSDEV_USERNAME + '_schema';
        let tableInfo = param.split('.');
        const schema = tableInfo.length > 1 ? tableInfo[0] : userSchema;
        const table = tableInfo.length > 1 ? tableInfo[1] : tableInfo[0];
        let cmd = {}
        cmd['command'] = `SELECT table_catalog, table_schema, column_name, data_type, is_nullable 
                          FROM information_schema.columns
                          WHERE table_schema = '${schema}' and table_name='${table}'`;
        cmds.push(cmd);
    }

    if ('sql' === command) {
        // process data from stdin (if any)
        const isPipe = fs.fstatSync(0).isFIFO();
        let sql = '';
        if (isPipe) {
            for await (const chunk of Bun.stdin.stream()) {
                // chunk is Uint8Array - this converts it to text (assumes ASCII encoding)
                sql += Buffer.from(chunk).toString();
            }

        } else {
            sql = await getFile(param);
        }

        const queries = sql
            .split(/;\s*(?=(?:[^'"]*['"][^'"]*['"])*[^'"]*$)/)
            .map(query => query.trim())
            .filter(query => query.length > 0);
        for (const query of queries) {
            let cmd = {}
            cmd['command'] = query;
            cmds.push(cmd);
        }
    }

    // call the system action
    try {
        for (const cmd of cmds) {
            const response = await fetch(`${psqlAddr}`, {
                method: "POST",
                body: JSON.stringify(cmd),
                headers: {'x-impersonate-auth': `${auth}`},
            });

            // format the output
            let outputData = '';
            const contentType = response.headers.get('Content-Type');
            const isJson = contentType && contentType.includes('application/json')

            if (isJson) {
                outputData = await response.json();
            } else {
                outputData = await response.text();
            }
            if (format === 'table' && isJson && outputData.length > 0) {
                console.log(Bun.inspect.table(outputData));
            } else {
                console.log(outputData);
            }
        }
    } catch (err) {
        console.error(`[ERROR]: ${err.message}`);
    }
}
