package NGCP::Panel::Controller::API::PasswordRecovery;
use NGCP::Panel::Utils::Generic qw(:all);

use Sipwise::Base;

use boolean qw(true);
use Data::HAL qw();
use Data::HAL::Link qw();
use HTTP::Headers qw();
use HTTP::Status qw(:constants);


sub allowed_methods{
    return [qw/POST OPTIONS/];
}

use parent qw/NGCP::Panel::Role::Entities NGCP::Panel::Role::API::PasswordRecovery/;

sub api_description {
    return 'Recover password following a password reset request.';
}

sub query_params {
    return [
    ];
}

sub resource_name{
    return 'passwordrecovery';
}

sub dispatch_path{
    return '/api/passwordrecovery/';
}

sub relation{
    return 'http://purl.org/sipwise/ngcp-api/#rel-passwordrecovery';
}

__PACKAGE__->set_config({
    action => {
        map { $_ => {
            Args => 0,
            Does => [qw(CheckTrailingSlash RequireSSL)],
            Method => $_,
            Path => __PACKAGE__->dispatch_path,
        } } @{ __PACKAGE__->allowed_methods },
    },
});

sub POST :Allow {
    my ($self, $c) = @_;

    my $res;

    $c->user->logout if($c->user);

    my $guard = $c->model('DB')->txn_scope_guard;
    {
        my $resource = $self->get_valid_post_data(
            c => $c,
            media_type => 'application/json',
        );
        last unless $resource;

        my $form = $self->get_form($c);
        last unless $self->validate_form(
            c => $c,
            resource => $resource,
            form => $form,
        );

        my ($uuid_bin, $uuid_string);
        $uuid_string = $resource->{token} // '';

        unless($uuid_string && UUID::parse($uuid_string, $uuid_bin) != -1) {
            $res = {success => 0};
            $self->error($c, HTTP_FORBIDDEN, 'Forbidden',
                         "Invalid password recovery attempt for token '$uuid_string' from '".$c->qs($c->req->address)."'");
            return;
        }

        my $redis = $c->redis_get_connection({database => $c->config->{'Plugin::Session'}->{redis_db}});
        unless ($redis) {
            $res = {success => 0};
            $self->error($c, HTTP_INTERNAL_SERVER_ERROR, 'Internal Server Error',
                         "Failed to connect to central redis url " . $c->config->{redis}->{central_url});
            return;
        }
        my $admin = $redis->hget("password_reset:admin::$uuid_string", "user");
        if ($admin) {
            $c->log->debug("Entering password recovery for administrator.");
            my $administrator = $c->model('DB')->resultset('admins')->search({login => $admin})->first;
            unless ($administrator) {
                $res = {success => 0};
                $self->error($c, HTTP_FORBIDDEN, 'Forbidden',
                             "Invalid password recovery attempt for token '$uuid_string' from '".$c->qs($c->req->address)."'");
                return;
            }
            my $ip = $redis->hget("password_reset:admin::$uuid_string", "ip");
            if ($ip && $ip ne $c->req->address) {
                $res = {success => 0};
                $self->error($c, HTTP_FORBIDDEN, 'Forbidden',
                             "Invalid password recovery attempt for token '$uuid_string' from '".$c->qs($c->req->address)."'");
                return;
            }
            $c->log->debug("Updating administrator password.");
            $administrator->update({
                saltedpass => NGCP::Panel::Utils::Auth::generate_salted_hash($form->params->{new_password}),
            });
            $redis->del("password_reset:admin::$uuid_string");
            $redis->del("password_reset:admin::$admin");
        }
        else {
            $c->log->debug("Entering password recovery for subscriber.");
            my $rs = $c->model('DB')->resultset('password_resets')->search({
                uuid => $uuid_string,
                timestamp => { '>=' => NGCP::Panel::Utils::DateTime::current_local->epoch - 300 },
            });

            my $subscriber = $rs->first ? $rs->first->voip_subscriber : undef;
            unless($subscriber && $subscriber->provisioning_voip_subscriber) {
                $res = {success => 0};
                $self->error($c, HTTP_FORBIDDEN, 'Forbidden',
                             "Invalid password recovery attempt for token '$uuid_string' from '".$c->qs($c->req->address)."'");
                return;
            }
            $c->log->debug("Updating subscriber password.");
            my $webpassword = $form->params->{new_password};
            $webpassword = NGCP::Panel::Utils::Auth::generate_salted_hash($webpassword) if $NGCP::Panel::Utils::Auth::ENCRYPT_SUBSCRIBER_WEBPASSWORDS;
            $subscriber->provisioning_voip_subscriber->update({
                webpassword => $webpassword,
            });
            $rs->delete;
        }

        $guard->commit;

        $res = { success => 1, message => 'Password reset successfully completed.' };

        $c->response->status(HTTP_OK);
        $c->response->body(JSON::to_json($res));
    }
    return;
}

1;

# vim: set tabstop=4 expandtab:
