#! /usr/bin/env perl
# vim: set filetype=perl ts=4 sw=4 sts=4 et:
use common::sense;

use File::Basename;
use lib dirname(__FILE__) . '/../../../lib/perl';
use OVH::Result;
use OVH::Bastion;
use OVH::Bastion::Plugin qw( :DEFAULT help );

my ($indexToDelete);
my $remainingOptions = OVH::Bastion::Plugin::begin(
    argv    => \@ARGV,
    header  => "Here are the public keys that allow you to connect to the bastion",
    options => {
        "line-number-to-delete=i"   => \$indexToDelete,             # compat, no longer documented since v3.02.00
        "id-to-delete|l=i"          => \$indexToDelete,             # -l is no longer documented since v3.23.01
        "fingerprint-to-delete|f=s" => \my $fingerprintToDelete,    # -f is no longer documented since v3.23.01
    },
    helptext => <<"EOF",
Remove an ingress public key from your account

Usage: --osh SCRIPT_NAME [--id-to-delete ID] [--fingerprint-to-delete FP]

  --id-to-delete ID           Directly specify key id to delete (CAUTION!), you can get id with selfListIngressKeys
  --fingerprint-to-delete FP  Directly specify the fingerprint of the key to delete (CAUTION!)

If none of these options are specified, you'll be prompted interactively.
EOF
);

#
# code
#
my $fnret;

if ($fingerprintToDelete and defined $indexToDelete) {
    help();
    osh_exit 'ERR_INCOMPATIBLE_PARAMETERS',
      "You can't specify a line to delete AND a fingerprint to delete at the same time";
}

# first, get all the authorized_keys present in the file
my $allowedKeyFile = $HOME . '/' . OVH::Bastion::AK_FILE;
$fnret =
  OVH::Bastion::get_authorized_keys_from_file(file => $allowedKeyFile, includeInvalid => 1, includePivDisabled => 1);
$fnret or osh_exit $fnret;

my %fingerprint2index;
my %validKeys;

# FIXME check cases with piv disabled keys, RSA keys not respecting the config (too small), and fully invalid keylines
foreach my $key (@{$fnret->value || []}) {
    OVH::Bastion::print_public_key(key => $key, id => $key->{'index'}, err => $key->{'err'});
    $fingerprint2index{$key->{'fingerprint'}} = $key->{'index'}
      if (OVH::Bastion::is_valid_fingerprint(fingerprint => $key->{'fingerprint'}));
    $validKeys{$key->{'index'}} = $key if $key->{'err'} eq 'OK';
}

# Do we have anything to delete ?
if (!%validKeys) {
    warn_syslog("User $self has no valid keys, but somehow connected successfully, this shouldn't happen");
    osh_exit 'ERR_NO_KEY', "You have no key to delete (wait, how did you connect in the first place?!)";
}
elsif (keys %validKeys == 1) {
    osh_exit 'ERR_ONLY_ONE_KEY', "You can't delete the only valid key you have!";
}
elsif (not defined $indexToDelete and not defined $fingerprintToDelete) {
    osh_info "Type the key ID you want to delete then press ENTER ("
      . (join(',', sort { $a <=> $b } keys %validKeys)) . "):";
    $indexToDelete = <STDIN>;
    chomp $indexToDelete;
}

if (defined $fingerprintToDelete) {
    if (not exists($fingerprint2index{$fingerprintToDelete})) {
        osh_exit 'ERR_NO_MATCH', "Couldn't find any key matching this fingerprint";
    }
    $indexToDelete = $fingerprint2index{$fingerprintToDelete};
}

if ($indexToDelete =~ /^(\d+)$/) {
    $indexToDelete = $1;    # untaint
}
else {
    osh_exit 'ERR_INVALID_PARAMETER', "Invalid number specified";
}

# here, either indexToDelete has been specified or we just got it from STDIN

if (not exists $validKeys{$indexToDelete}) {
    osh_exit 'ERR_INVALID_ID', "Bad key ID";
}

my $deletedKey = delete $validKeys{$indexToDelete};

# data: keep the keys order in the new file, instead of having it randomized
$fnret = OVH::Bastion::put_authorized_keys_to_file(
    file => $allowedKeyFile,
    data => [map { $validKeys{$_} } sort keys %validKeys]
);
$fnret or osh_exit $fnret;

osh_exit R('OK', msg => "Key ID $indexToDelete successfully deleted", value => {deleted_key => $deletedKey});
