#!/usr/bin/perl

use strict;
use warnings;
use Getopt::Long;
use Pod::Usage;
use File::Spec;

use Crypt::TSD;
use LWP::UserAgent;
use Digest::SHA qw(sha512);

# Command line options
my $help = 0;
my $version = 0;
my $output_file;
my $hash_algorithm = 'sha512';
my $verbose = 0;

# Parse command line options
GetOptions(
    'help|h' => \$help,
    'version' => \$version,
    'output|o=s' => \$output_file,
    'algorithm|a=s' => \$hash_algorithm,
    'verbose|v' => \$verbose,
) or pod2usage(2);

# Show help
if ($help) {
    pod2usage(-verbose => 2);
    exit 0;
}

# Show version
if ($version) {
    print "tsd-timestamp version $Crypt::TSD::VERSION\n";
    exit 0;
}

# Get input file from command line
my $input_file = shift @ARGV;
if (!$input_file) {
    print "Error: Input file required\n";
    pod2usage(1);
}

# Check if input file exists
unless (-f $input_file) {
    die "Error: Input file '$input_file' not found\n";
}

# Generate output filename if not provided
unless ($output_file) {
    $output_file = $input_file;
    $output_file =~ s/\.([^.]+)$/.tsr/;
}

print "Getting timestamp from FreeTSA...\n" if $verbose;
print "Input file: $input_file\n" if $verbose;
print "Output file: $output_file\n" if $verbose;
print "Hash algorithm: $hash_algorithm\n" if $verbose;

# Read input file
my $file_data;
{
    open my $fh, '<:raw', $input_file or die "Cannot open input file '$input_file': $!\n";
    local $/;
    $file_data = <$fh>;
    close $fh;
}

print "File size: " . length($file_data) . " bytes\n" if $verbose;

# Create timestamp request
my $tsq_file = $input_file . '.tsq';
my $tsq_cmd = "openssl ts -query -data '$input_file' -no_nonce -$hash_algorithm -cert -out '$tsq_file'";
print "Creating timestamp request...\n" if $verbose;
print "Command: $tsq_cmd\n" if $verbose;

system($tsq_cmd) == 0 or die "Failed to create timestamp request: $!\n";

# Send request to FreeTSA
print "Sending request to FreeTSA...\n" if $verbose;
my $ua = LWP::UserAgent->new(timeout => 30);
my $response = $ua->post('https://freetsa.org/tsr',
    'Content-Type' => 'application/timestamp-query',
    Content => do {
        open my $fh, '<:raw', $tsq_file or die "Cannot read TSQ file: $!\n";
        local $/;
        <$fh>;
    }
);

unless ($response->is_success) {
    die "Failed to get timestamp from FreeTSA: " . $response->status_line . "\n";
}

# Save timestamp response
open my $fh, '>:raw', $output_file or die "Cannot create output file '$output_file': $!\n";
print $fh $response->content;
close $fh;

print "Timestamp received and saved to: $output_file\n";
print "Timestamp size: " . length($response->content) . " bytes\n" if $verbose;

# Clean up TSQ file
unlink $tsq_file if -f $tsq_file;

print "Done!\n";

__END__

=head1 NAME

tsd-timestamp - Get a timestamp from FreeTSA for a file

=head1 VERSION

version 0.01_05

=head1 SYNOPSIS

tsd-timestamp [options] input_file

Options:
    -o, --output FILE       Output .tsr file (default: input_file.tsr)
    -a, --algorithm ALG     Hash algorithm (default: sha512)
    -v, --verbose           Verbose output
    -h, --help              Show this help
    --version               Show version

=head1 DESCRIPTION

Gets a timestamp from FreeTSA.org for a file. The file is hashed using the
specified algorithm and sent to FreeTSA to get a timestamp token.

=head1 EXAMPLES

    # Get timestamp for a file
    tsd-timestamp document.pdf

    # Specify output file
    tsd-timestamp -o my_timestamp.tsr document.pdf

    # Use different hash algorithm
    tsd-timestamp -a sha256 document.pdf

    # Verbose output
    tsd-timestamp -v document.pdf

=head1 SEE ALSO

L<Crypt::TSD>, L<Crypt::TimestampedData>

=cut
