import { loadConfig } from '../infrastructure/config.js';
import { formatTable, truncEnd } from './table.js';
/**
 * Print data as newline-delimited JSON (NDJSON).
 *
 * Emits a `_meta` line with pagination info (if present), then one JSON
 * line per item in the named array field.
 */
export function printNdjson(data, field) {
    if (data._pagination)
        console.log(JSON.stringify({ _meta: data._pagination }));
    const items = data[field];
    if (Array.isArray(items)) {
        // console.log is intentional: NDJSON serialisation must go to stdout, not the structured logger
        for (const item of items)
            console.log(JSON.stringify(item));
    }
}
function flattenObject(obj, prefix = '') {
    const result = {};
    for (const [key, value] of Object.entries(obj)) {
        const fullKey = prefix ? `${prefix}.${key}` : key;
        if (value !== null &&
            typeof value === 'object' &&
            !Array.isArray(value) &&
            Object.getPrototypeOf(value) === Object.prototype) {
            Object.assign(result, flattenObject(value, fullKey));
        }
        else if (Array.isArray(value)) {
            result[fullKey] = JSON.stringify(value);
        }
        else {
            result[fullKey] = value;
        }
    }
    return result;
}
function prepareFlatItems(data, field) {
    const items = field ? data[field] : data;
    if (!Array.isArray(items))
        return null;
    const flatItems = items.map((item) => typeof item === 'object' && item !== null && !Array.isArray(item)
        ? flattenObject(item)
        : { value: item });
    const columns = (() => {
        const keys = new Set();
        for (const item of flatItems)
            for (const key of Object.keys(item))
                keys.add(key);
        return [...keys];
    })();
    if (columns.length === 0)
        columns.push('value');
    return { flatItems, columns };
}
function escapeCsv(val) {
    const str = val == null ? '' : String(val);
    if (str.includes(',') || str.includes('"') || str.includes('\n') || str.includes('\r')) {
        return `"${str.replace(/"/g, '""')}"`;
    }
    return str;
}
function printCsv(data, field) {
    const prepared = prepareFlatItems(data, field);
    if (!prepared)
        return false;
    const { flatItems, columns } = prepared;
    console.log(columns.map(escapeCsv).join(','));
    for (const row of flatItems) {
        console.log(columns.map((col) => escapeCsv(row[col])).join(','));
    }
    return true;
}
const MAX_COL_WIDTH = 40;
function printAutoTable(data, field, displayOpts = {}) {
    const prepared = prepareFlatItems(data, field);
    if (!prepared)
        return false;
    const { flatItems, columns } = prepared;
    const colWidth = displayOpts.maxColWidth ?? MAX_COL_WIDTH;
    const colDefs = columns.map((col) => {
        const maxLen = flatItems.reduce((max, item) => Math.max(max, String(item[col] ?? '').length), col.length);
        const isNumeric = flatItems.length > 0 &&
            flatItems.every((item) => {
                const v = item[col];
                return v == null || v === '' || (typeof v !== 'boolean' && Number.isFinite(Number(v)));
            });
        return {
            header: col,
            width: Math.min(maxLen, colWidth),
            align: isNumeric ? 'right' : 'left',
        };
    });
    const rows = flatItems.map((item) => columns.map((col) => truncEnd(String(item[col] ?? ''), colWidth)));
    console.log(formatTable({ columns: colDefs, rows }));
    return true;
}
export function outputResult(data, field, opts) {
    if (opts.ndjson) {
        if (field === null) {
            // No field key — emit the whole object as a single NDJSON line
            console.log(JSON.stringify(data));
        }
        else {
            printNdjson(data, field);
        }
        return true;
    }
    if (opts.json) {
        console.log(JSON.stringify(data, null, 2));
        return true;
    }
    if (opts.csv) {
        return printCsv(data, field) !== false;
    }
    if (opts.table) {
        const displayOpts = opts.display ?? loadConfig().display;
        return printAutoTable(data, field, displayOpts) !== false;
    }
    return false;
}
//# sourceMappingURL=result-formatter.js.map