export type LogLevel = 'debug' | 'info' | 'warn' | 'error';
export type LogDepth = 'normal' | 'verbose' | 'profiling';
export type LogType = 'http' | 'app' | 'auth' | 'profiling';

export interface LogHeader {
    timestamp: string;
    level: LogLevel;
    depth: LogDepth;
    type: LogType; // 'http', 'app', 'db', etc.
    user_id?: number;
}

export interface LogPayload {
    message?: string;              // short human-friendly description
    data?: Record<string, any>;    // type-specific rich data
}

// Environment defaults
const CURRENT_DEPTH: LogDepth = (process.env.LOG_DEPTH as LogDepth) || 'normal';

const DEPTH_ORDER: Record<LogDepth, number> = { normal: 0, verbose: 1, profiling: 2 };

function shouldLog(depth: LogDepth) {
    let should = DEPTH_ORDER[depth] <= DEPTH_ORDER[CURRENT_DEPTH]
    return should;
}

function emitLog(header: LogHeader, payload: LogPayload = {}) {
    if (!shouldLog(header.depth)) return;

    const logLine = { ...header, ...payload };

    if (header.level === 'error')
        console.error(JSON.stringify(logLine))
    else
        console.log(JSON.stringify(logLine));
}

export const logger = {
    log(level: LogLevel, type: LogType, message: string, data?: Record<string, any>, depth: LogDepth = 'normal', context?: Partial<LogHeader>) {
        const header: LogHeader = {
            timestamp: new Date().toISOString(),
            level,
            depth,
            type,
            ...context,
        };

        const payload: LogPayload = {
            message,
            data,
        };

        emitLog(header, payload);
    },

    info(type: LogType, message: string, data?: Record<string, any>, depth: LogDepth = 'normal', context?: Partial<LogHeader>) {
        this.log('info', type, message, data, depth, context);
    },

    debug(type: LogType, message: string, data?: Record<string, any>, depth: LogDepth = 'normal', context?: Partial<LogHeader>) {
        this.log('debug', type, message, data, depth, context);
    },

    warn(type: LogType, message: string, data?: Record<string, any>, depth: LogDepth = 'normal', context?: Partial<LogHeader>) {
        this.log('warn', type, message, data, depth, context);
    },

    error(type: LogType, message: string, data?: Record<string, any>, depth: LogDepth = 'normal', context?: Partial<LogHeader>) {
        this.log('error', type, message, data, depth, context);
    },
}