package Net::OpenVPN::Manager::Plugin::ClientProfile;

use namespace::autoclean;
use Moose;
use Net::OpenVPN::Manager::Plugin;
use Crypt::JWT qw(encode_jwt decode_jwt);
use JSON;
use Template;

with 'Net::OpenVPN::Manager::Startable';

has 'jwtkey' => (
    is => 'ro',
    isa => 'Str',
    required => 1,
);

has 'config' => (
    is => 'ro',
    isa => 'Str',
    required => 1,
);

sub start {
    my $self = shift;

    $self->manager->add_dispatcher(sub {
        my $env = shift;

        '/profile/...' => sub {
            'GET + /config/*.*' => sub {
                shift;
                my ($token) = @_;

                my $payload = eval {
                    return decode_jwt(
                        token => $token,
                        key => $self->jwtkey,
                        accepted_alg => "HS256",
                        verify_iat => 1,
                    );
                };

                if ($@) {
                    $self->log("unable to decode JWT token to get config file: $@");
                    return [404, ['Content-type', 'application/text'], ["unable to deliver profile"]];
                } elsif (!$payload->{username}) {
                    $self->log("unable to get username in JWT token to get config file");
                    return [404, ['Content-type', 'application/text'], ["unable to deliver profile"]];
                }

                my $t = Template->new();
                my $out;
                my $r = $t->process(\$self->config, $payload, \$out);

                if ($r != 1) {
                    return [500, ['Content-type', 'application/text'], ["Unable to process template"]];
                }

                [200, ['Content-type', 'application/x-openvpn-profile'], [$out]];
            },
        },
        '/api/profile/...' => sub {
            '' => sub {
                $self->manager->middleware_apikey;
            },
            'GET + /token/*' => sub {
                shift;
                my ($username) = @_;

                my $token = encode_jwt(
                    payload => { username => $username },
                    alg => "HS256",
                    auto_iat => 1,
                    relative_exp => 60,
                    key => $self->jwtkey,
                );

                $self->log("deliver JWT token to user $username to retrieve config file");
                [200, ['Content-type', 'application/json'], [to_json({token => $token})]];
            },
            'GET + /config/*' => sub {
                shift;
                my ($username) = @_;

                my $t = Template->new();
                my $out;
                my $r = $t->process(\$self->config, { username => $username }, \$out);

                if ($r != 1) {
                    return [500, ['Content-type', 'application/json'], [to_json({error => "Unable to process template"})]];
                }

                [200, ['Content-type', 'application/json'], [to_json({config => $out})]];
            },
        },
    });

    return PLUG_OK;
}

1;
