#!/usr/bin/perl

use strict;
use warnings;
use Getopt::Long;
use File::HomeDir;
use File::Spec;
use Cwd 'abs_path';

# --- Default key paths ---
my $default_private_key = File::Spec->catfile(File::HomeDir->my_home, '.ssh', 'id_ed25519');
my $default_public_key  = "$default_private_key.pub";

# --- Command-line options ---
my $user;
my $host;
my $key_file = $default_public_key;
my $generate = 0;
my $help     = 0;

GetOptions(
    'user=s'     => \$user,
    'host=s'     => \$host,
    'keyfile=s'  => \$key_file,
    'generate'   => \$generate,
    'help|?'     => \$help,
) or die "Error in command line arguments.\n";

# --- Help ---
if ($help || (!$generate && (!$user || !$host))) {
    print <<"USAGE";
Usage:
  To generate a new SSH key:
    $0 --generate [--keyfile /path/to/id_ed25519.pub]

  To install a key on a remote server:
    $0 --user <username> --host <hostname> [--keyfile /path/to/id_ed25519.pub]

Options:
  --generate         Generate a new Ed25519 SSH key
  --user             Remote server username
  --host             Remote server hostname or IP
  --keyfile          Path to the public key file (defaults to $default_public_key)
  --help             Show this help message
USAGE
    exit;
}

# --- Main Execution ---
if ($generate) {
    generate_ssh_key($key_file);
} elsif ($user && $host) {
    install_ssh_key($user, $host, $key_file);
} else {
    die "Error: Either --generate or both --user and --host must be provided.\n";
}

# --- Subroutines ---

sub generate_ssh_key {
    my ($pub_key_path) = @_;
    my $priv_key_path = $pub_key_path;
    $priv_key_path =~ s/\.pub$//;

    if (-e $priv_key_path || -e $pub_key_path) {
        print "An SSH key already exists at:\n";
        print "  Private: $priv_key_path\n";
        print "  Public:  $pub_key_path\n";
        print "Overwrite existing key? [y/N]: ";
        my $response = <STDIN>;
        chomp($response);
        if (lc($response) ne 'y') {
            print "Key generation aborted.\n";
            return;
        }
        unlink $priv_key_path, $pub_key_path;
    }

    # Ensure ~/.ssh exists
    my $ssh_dir = File::Spec->catdir(File::HomeDir->my_home, '.ssh');
    mkdir $ssh_dir, 0700 unless -d $ssh_dir;

    print "Generating a new Ed25519 SSH key pair...\n";
    my $command = "ssh-keygen -t ed25519 -f \"$priv_key_path\" -N '' 2>&1";
    my $output = `$command`;

    if ($? == 0) {
        print "Key successfully generated:\n";
        print "  Private: $priv_key_path\n";
        print "  Public:  $pub_key_path\n";
    } else {
        die "ssh-keygen failed:\n$output\n";
    }
}

sub install_ssh_key {
    my ($remote_user, $remote_host, $pub_key_path) = @_;

    unless (-e $pub_key_path) {
        die "Error: Public key not found at $pub_key_path\n";
    }

    print "\nInstalling SSH key to $remote_user\@$remote_host...\n";
    print "You may be prompted for a password.\n";

    my $command = "ssh-copy-id -i \"$pub_key_path\" $remote_user\@$remote_host";
    system($command);

    if ($? == 0) {
        print "\nKey successfully installed. You can now SSH without a password:\n";
        print "  ssh $remote_user\@$remote_host\n";
    } else {
        warn "\nssh-copy-id failed (exit code $?). Check for errors above.\n";
    }
}
