#!/usr/bin/env perl

use strict;
use warnings;
use JSON::PP;
use IO::File;
use FindBin;
use lib "$FindBin::Bin/../lib";
use JQ::Lite;

# Show help if no arguments are given
if (!@ARGV) {
    print <<'USAGE';
jq-lite - A lightweight jq-like JSON query tool written in pure Perl

Usage:
  jq-lite [options] '.query' [file.json]

Options:
  -r, --raw-output    Print raw strings instead of JSON-encoded values
  -h, --help          Show this help message

Examples:
  cat users.json | jq-lite '.users[].name'
  jq-lite '.users[] | select(.age > 25)' users.json
  jq-lite -r '.users[] | .name' users.json
  jq-lite '.meta has "version"' config.json
  jq-lite '.items | sort | reverse | first' data.json

Query Syntax:
  .key                Access a key (e.g. .user.name)
  .key?               Optional access (no error if missing)
  .array[]            Traverse all array elements
  .array[n]           Index into array
  |                   Pipe to next operation
  select(condition)   Filter values
  Built-in functions: length, keys, first, last, reverse, sort, unique, has

Tips:
  - Query must start with a dot (e.g. '.users[]')
  - Reads from STDIN if no file is provided
  - Outputs JSON by default; use -r for plain text

Homepage:
  https://metacpan.org/pod/JQ::Lite
USAGE
    exit 0;
}

# Argument parsing
my $raw_output = 0;
my $query;
my $filename;

while (@ARGV) {
    my $arg = shift @ARGV;
    if ($arg eq '--raw-output' || $arg eq '-r') {
        $raw_output = 1;
    }
    elsif ($arg eq '--help' || $arg eq '-h') {
        print <<'USAGE';
jq-lite - A lightweight jq-like JSON query tool written in pure Perl

Usage:
  jq-lite [options] '.query' [file.json]

Options:
  -r, --raw-output    Print raw strings instead of JSON-encoded values
  -h, --help          Show this help message

Examples:
  cat users.json | jq-lite '.users[].name'
  jq-lite '.users[] | select(.age > 25)' users.json
  jq-lite -r '.users[] | .name' users.json
  jq-lite '.meta has "version"' config.json
  jq-lite '.items | sort | reverse | first' data.json

Query Syntax:
  .key                Access a key (e.g. .user.name)
  .key?               Optional access (no error if missing)
  .array[]            Traverse all array elements
  .array[n]           Index into array
  |                   Pipe to next operation
  select(condition)   Filter values
  Built-in functions: length, keys, first, last, reverse, sort, unique, has

Tips:
  - Query must start with a dot (e.g. '.users[]')
  - Reads from STDIN if no file is provided
  - Outputs JSON by default; use -r for plain text

Homepage:
  https://metacpan.org/pod/JQ::Lite
USAGE
        exit 0;
    }
    elsif (!defined $query && $arg =~ /^\./) {
        $query = $arg;
    }
    elsif (!defined $query && !-f $arg) {
        die "Error: Invalid query syntax '$arg'\nUsage: jq-lite [--raw-output|-r] '.query' [file.json]\n";
    }
    elsif (!defined $query) {
        $filename = $arg;
    }
    elsif (!defined $filename) {
        $filename = $arg;
    }
    else {
        die "Usage: jq-lite [--raw-output|-r] '.query' [file.json]\n";
    }
}

# Load JSON from file or STDIN
my $json_text;
if (defined $filename) {
    open my $fh, '<', $filename or die "Cannot open file '$filename': $!\n";
    local $/;
    $json_text = <$fh>;
    close $fh;
}
else {
    local $/;
    $json_text = <STDIN>;
}

# Create JQ::Lite object
my $jq = JQ::Lite->new(raw => $raw_output);

# Interactivity support
sub print_results {
    my @results = @_;
    if ($raw_output) {
        for my $r (@results) {
            print defined($r) && ref($r) eq '' ? "$r\n" : "null\n";
        }
    } else {
        my $pp = JSON::PP->new->utf8->canonical->pretty;
        for my $r (@results) {
            print defined($r) ? $pp->encode($r) : "null\n";
        }
    }
}

# Interactive mode
if (!defined $query) {
    my $tty = IO::File->new("/dev/tty", "r") or die "Cannot open /dev/tty: $!";
    print "jq-lite interactive mode. Enter query (empty line to quit):\n";
    while (1) {
        print "> ";
        my $line = <$tty>;
        last unless defined $line;
        chomp $line;
        last if $line =~ /^\s*$/;

        my @results = eval { $jq->run_query($json_text, $line) };
        if ($@) {
            warn "[ERROR] Invalid query: $@\n";
            next;
        }

        if (!@results) {
            warn "[INFO] No results returned for query.\n";
            next;
        }

        eval {
            system("clear");
            print_results(@results);
            1;
        } or do {
            my $e = $@ || 'Unknown error';
            warn "[ERROR] Failed to print result: $e\n";
        };
    }
    exit 0;
}

# One-shot mode
my @results = eval { $jq->run_query($json_text, $query) };
if ($@) {
    die "[ERROR] Invalid query: $@\n";
}

if (!@results) {
    warn "[INFO] No results returned for query.\n";
    exit 1;
}

print_results(@results);
