const std = @import("std");
const terminal = @import("../utils/terminal.zig");

/// Output mode: JSON for structured data, text for TSV
pub const Mode = enum { json, text };

pub var mode: Mode = .text;

pub fn setMode(m: Mode) void {
    mode = m;
}

/// Escape a value for TSV output (replace tabs/newlines with spaces for xargs safety)
fn escapeTSV(val: []const u8) []const u8 {
    // For xargs usability, we need single-line output with no tabs/newlines in values
    // This returns the same slice if no escaping needed, but we process to ensure safety
    // In practice, we just use the value directly since the caller should sanitize
    return val;
}

/// Check if value needs TSV escaping
fn needsTSVEscape(val: []const u8) bool {
    for (val) |c| {
        if (c == '\t' or c == '\n' or c == '\r') return true;
    }
    return false;
}

/// Print error to stderr
pub fn err(msg: []const u8) void {
    std.debug.print("Error: {s}\n", .{msg});
}

/// Print line in current mode (JSON or TSV)
pub fn line(values: []const []const u8) void {
    switch (mode) {
        .json => {
            std.debug.print("{{", .{});
            // Assume alternating key-value pairs
            var i: usize = 0;
            while (i < values.len) : (i += 2) {
                if (i > 0) std.debug.print(",", .{});
                const key = values[i];
                const val = if (i + 1 < values.len) values[i + 1] else "";
                std.debug.print("\"{s}\":\"{s}\"", .{ key, val });
            }
            std.debug.print("}}\n", .{});
        },
        .text => {
            for (values, 0..) |val, i| {
                if (i > 0) std.debug.print("\t", .{});
                // For TSV/xargs safety: if value contains tabs/newlines, we need to handle it
                // Simple approach: print as-is but replace internal tabs with spaces
                if (needsTSVEscape(val)) {
                    for (val) |c| {
                        if (c == '\t' or c == '\n' or c == '\r') {
                            std.debug.print(" ", .{});
                        } else {
                            std.debug.print("{c}", .{c});
                        }
                    }
                } else {
                    std.debug.print("{s}", .{val});
                }
            }
            std.debug.print("\n", .{});
        },
    }
}

/// Print raw JSON array
pub fn jsonArray(items: []const []const u8) void {
    std.debug.print("[", .{});
    for (items, 0..) |item, i| {
        if (i > 0) std.debug.print(",", .{});
        std.debug.print("\"{s}\"", .{item});
    }
    std.debug.print("]\n", .{});
}

/// Print raw JSON object from key-value pairs
pub fn jsonObject(pairs: []const []const u8) void {
    std.debug.print("{{", .{});
    var i: usize = 0;
    while (i < pairs.len) : (i += 2) {
        if (i > 0) std.debug.print(",", .{});
        const key = pairs[i];
        const val = if (i + 1 < pairs.len) pairs[i + 1] else "";
        std.debug.print("\"{s}\":\"{s}\"", .{ key, val });
    }
    std.debug.print("}}\n", .{});
}

/// Print success response (JSON only)
pub fn success(comptime cmd: []const u8) void {
    if (mode == .json) {
        std.debug.print("{{\"success\":true,\"command\":\"{s}\"}}\n", .{cmd});
    }
}

/// Print success with data
pub fn successData(comptime cmd: []const u8, pairs: []const []const u8) void {
    if (mode == .json) {
        std.debug.print("{{\"success\":true,\"command\":\"{s}\",\"data\":{{", .{cmd});
        var i: usize = 0;
        while (i < pairs.len) : (i += 2) {
            if (i > 0) std.debug.print(",", .{});
            const key = pairs[i];
            const val = if (i + 1 < pairs.len) pairs[i + 1] else "";
            std.debug.print("\"{s}\":\"{s}\"", .{ key, val });
        }
        std.debug.print("}}}}\n", .{});
    } else {
        for (pairs, 0..) |val, i| {
            if (i > 0) std.debug.print("\t", .{});
            std.debug.print("{s}", .{val});
        }
        std.debug.print("\n", .{});
    }
}

/// Print usage information
pub fn usage(comptime cmd: []const u8, comptime u: []const u8) void {
    std.debug.print("Usage: {s} {s}\n", .{ cmd, u });
}

/// Print plain value (text mode only)
pub fn value(v: []const u8) void {
    if (mode == .text) {
        std.debug.print("{s}\n", .{v});
    }
}

/// Get terminal width for formatting
pub fn getTerminalWidth() ?usize {
    return terminal.getWidth();
}
