#!/usr/bin/perl
use strict;
use warnings;
use CGI;
use CGI::Carp qw(fatalsToBrowser);
use feature qw(say);
use Data::Dumper;
use JSON qw( decode_json );
use LWP;
use DateTime;
use DateTime::Format::MySQL;

my $decoded_json;
my $cgi = CGI->new();
my $ua = LWP::UserAgent->new();

my %config = (
    'HOST_WHITELIST' => [ '37.120.171.21' ],
    'PHP_CRUD_API_URL' => 'https://terminsnipe:y9aFwUO7htuyKMaaPQWu@service.berlin.de.zinomedia.de/www/lib/terminsnipe/php-crud-api/api.php',
    'MBPR_API_KEY' => 'sKjdz2pUHx',
);

print $cgi->header(-type => 'application/json', -access_control_allow_origin => '*', -charset => 'utf-8');
open (my $LOG, '>', 'log.txt'); # open filehandle log.txt
select $LOG; # select new filehandle
# say 'This should be logged.';
# select STDOUT; # restore STDOUT


# WORKFLOW
print $cgi->header(-type => 'application/json', -access_control_allow_origin => '*', -charset => 'utf-8');
#print $cgi->header();
# print Dumper $cgi->url_param();


# foreach my $key (sort(keys(%ENV))) {
#     print "$key = $ENV{$key}<br>\n";
# }
my $timestamp = localtime(time);
say "RUN @ $timestamp";

&validate_request();
&routes();


# PRINT REVEIVED JSON TO FILE
#&dumpToFile("./POSTDATA_$timestamp", $decoded_json);

sub routes {
    &Delimiter((caller(0))[3]);  
    
    print Dumper $decoded_json;
    # if ($decoded_json->{'event'} eq 'member-added') {
    #     say 'member_added';
    #     &event_member_added();
    # }
    if ($decoded_json->{'event'} eq 'member-signup-completed') {
        say 'member-signup-completed';
        &event_member_signup_completed();
    }
    elsif ($decoded_json->{'event'} eq 'ninjaforms-terminerstellung') {
        say 'ninjaforms-terminerstellung';
        &event_ninjaforms_terminerstellung();
    }
    elsif ($decoded_json->{'event'} eq 'restapi-delete-user') {
        say 'restapi-delete-user';
        &event_restapi_delete_user();
    }
    else {
        say $decoded_json->{'event'} . ' not handled yet';
    }
}
sub event_restapi_delete_user {
    &Delimiter((caller(0))[3]);
    
    if( !$decoded_json->{'WP_ID'} ) {
        say 'Missing args in event_restapi_delete_user';
        return;
    }
    
    # TRIGGER DELETE MBPR EVENT VIA API
    say 'Triggering Memberpress REST-API to delete user with WP_ID: '. $decoded_json->{'WP_ID'};
    my $url_delete_mbpr = 'https://zinomedia.de/wp_hq/terminsnipe/wp-json/mp/v1/members/' . $decoded_json->{'WP_ID'};
    my $response = $ua->delete( $url_delete_mbpr, 'Authorization' => $config{'MBPR_API_KEY'});
    #print Dumper $response;
    
    # GET USER_ID FROM WP_ID
    say 'Getting USER_ID from WP_ID...';
    my $query = "records/reg_users?filter=WP_ID,eq,$decoded_json->{'WP_ID'}&include=ID";
    my $url_get = "$config{'PHP_CRUD_API_URL'}/$query";
    my $response2 = &lwp_get($url_get);
    my $user_id = $response2->{'records'}[0]->{'ID'};
    
    # DELETE USER FROM DB
    my $query2 = 'records/reg_users/' . $user_id;
    my $url_delete_db = "$config{'PHP_CRUD_API_URL'}/$query2";
    my $response3 = $ua->delete( $url_delete_db );
    #print Dumper $response3;
    say 'Deleting user from db with ID: ' . $user_id . ' ... done';
}
sub event_ninjaforms_terminerstellung {
    &Delimiter((caller(0))[3]);
    
    # GET USER_ID FROM WP_ID
    my $query = "records/reg_users?filter=WP_ID,eq,$decoded_json->{'WP_ID'}&include=ID";
    my $url_get = "$config{'PHP_CRUD_API_URL'}/$query";
    my $response = &lwp_get($url_get);
    my $user_id = $response->{'records'}[0]->{'ID'};
    
    # DATETIMES
    my ($datetime_to, $datetime_from);
    if ($decoded_json->{'SWITCH_TERMINTYPE'} eq 'sofort') {
        my $dt = DateTime->now;
        $dt->set_time_zone( 'Europe/Berlin' );
        $datetime_from = DateTime::Format::MySQL->format_datetime($dt);
        $datetime_to = "$decoded_json->{'WOCHENTAG_END'} $decoded_json->{'UHRZEIT_END'}";
    }
    elsif ($decoded_json->{'SWITCH_TERMINTYPE'} eq 'zeitraum') {
        $datetime_from = "$decoded_json->{'WOCHENTAG_START'} $decoded_json->{'UHRZEIT_START'}";
        $datetime_to = "$decoded_json->{'WOCHENTAG_END'} $decoded_json->{'UHRZEIT_END'}";
    }
    
    # INSERT INTO request
    my %data = (
                'USER_ID' => $user_id,
                'SERVICE_ID' => $decoded_json->{'SERVICE_ID'},
                'DATETIME_FROM' => $datetime_from,
                'DATETIME_TO' => $datetime_to,
                );
    my $request_id = &post_request(\%data, "$config{'PHP_CRUD_API_URL'}/records/request");
    
    # STANDORTE
    my @standorte;
    if ($decoded_json->{'SWITCH_STANDORTE'} eq 'berlinweit') {
        my $query = "records/services/$decoded_json->{'SERVICE_ID'}?include=HREF";
        my $url_get = "$config{'PHP_CRUD_API_URL'}/$query";
        my $response = &lwp_get($url_get);
        my $href = $response->{'HREF'};
        $href =~ m/dienstleisterlist=(.*?)\&/;
        @standorte= split(/,/, $1);
    }
    elsif ($decoded_json->{'SWITCH_STANDORTE'} eq 'standorte-auswaehlen') {
        @standorte = split(/,/, $decoded_json->{'STANDORTE'});
    }
    print Dumper \@standorte;
    
    # INSERT INTO request_dienstleister
    for my $venue_id (@standorte) {
        my %data_request_dienstleister = (
            'REQUEST_ID' => $request_id,
            'VENUE_ID' => $venue_id,
        );
        my $request_dienstleister_id = &post_request(\%data_request_dienstleister, "$config{'PHP_CRUD_API_URL'}/records/request_dienstleister");
    }
}
sub lwp_get {
    &Delimiter((caller(0))[3]);
    my ($url) = @_;
    
    say "GETTING $url...";
    
    my $response = $ua->get($url);
    if ($response->is_success) {
        return decode_json($response->decoded_content);
    }
    else {
        say "LWP not successful";
        say $response->status_line;
        exit;
    }
}
sub post_request {
    &Delimiter((caller(0))[3]);
    my ($data_ref, $url) = @_;
    
    print Dumper $data_ref;
    say "Posting $url...";
    
    my $response = $ua->post( $url, { %$data_ref } );
    return $response->decoded_content();
}
sub event_member_signup_completed {
    &Delimiter((caller(0))[3]);
    
    my %data = (
                'EMAIL' => $decoded_json->{'data'}->{'email'},
                'WP_ID' => $decoded_json->{'data'}->{'id'},
                'LAST_NAME' => $decoded_json->{'data'}->{'last_name'},
                'FIRST_NAME' => $decoded_json->{'data'}->{'first_name'},
                'PHONE' => $decoded_json->{'data'}->{'profile'}->{'mepr_telefon_mobil'},
                );
    print Dumper \%data;
    
    # CHECK IF USER ALREADY EXISTS IN DB
    my $url_get = "$config{'PHP_CRUD_API_URL'}/records/reg_users?filter=WP_ID,eq,$data{'WP_ID'}";
    my $response = &lwp_get($url_get);
    say 'Number of existing records ' . scalar @{$response->{'records'}};
    print Dumper $response;
    
    # INSERT NEW USER IF NOT ALREADY IN DB
    if (scalar @{$response->{'records'}} == 0) {
        say "Inserting new user...";
        &post_request(\%data, "$config{'PHP_CRUD_API_URL'}/records/reg_users");
    }
    else {
        say 'Already ' . @{$response->{'records'}} . ' datasets exist -> No db insert.';
    }
}
sub validate_request {
    &Delimiter((caller(0))[3]);
    
    if (!grep( /^$ENV{'REMOTE_ADDR'}$/, @{$config{'HOST_WHITELIST'}})) {
        say "HOST $ENV{'REMOTE_ADDR'} not whitelisted.";
        exit;
    }

    if ($cgi->param("POSTDATA")) {  # MEMBERPRESS
        say "Memberpress entered. We have data.";
        &decode_received_json($cgi->param("POSTDATA"));
    }
    elsif (!$cgi->param("POSTDATA")) {
        say "No data received.";
        exit;
    }
}
sub decode_received_json {
    &Delimiter((caller(0))[3]);  
    my $data = @_;
    
    $decoded_json = eval { decode_json($cgi->param("POSTDATA")) };
    if ($@) {
        say "decode_json failed, invalid json.";
        say $@;
        exit;
    }
}
sub dumpToFile {
    # &Delimiter((caller(0))[3]);
    my ($filepath, $ref) = @_;
    
    # DATA DUMPER UTF8 HACK
    # no warnings 'redefine';
    local *Data::Dumper::qquote = sub { qq["${\(shift)}"] };
    local $Data::Dumper::Useperl = 1;
    
    #open my $FILE, '>:encoding(UTF-8)', $filepath;
    open( my $FILE, '>:encoding(UTF-8)', $filepath ) or die "Couldn't open: $!";
    print $FILE Dumper $ref;
    close $FILE;
}
sub Delimiter {
    my $SubName = shift;
    print "\n" . "-" x 80 . "\n";
    print "> " . $SubName;
    # print " | CHILD: $service_id_fork" if ($service_id_fork);
    print "\n" . '-' x 80 . "\n";
}



# print <<'END';
# <!doctype html>
# <html> $local </html>
# END

# sub output_top($);
# sub output_end($);
# sub display_results($);
# sub output_form($);

# my $q = new CGI;

# print $q->header();

# # Output stylesheet, heading etc
# output_top($q);

# if ($q->param()) {
#     # Parameters are defined, therefore the form has been submitted
#     display_results($q);
# } else {
#     # We're here for the first time, display the form
#     output_form($q);
# }

# # Output footer and end html
# output_end($q);

# exit 0;

# # Outputs the start html tag, stylesheet and heading
# sub output_top($) {
#     my ($q) = @_;
#     print $q->start_html(
#         -title => 'A Questionaire',
#         -bgcolor => 'white');
# }

# # Outputs a footer line and end html tags
# sub output_end($) {
#     my ($q) = @_;
#     print $q->div("My Web Form");
#     print $q->end_html;
# }

# # Displays the results of the form
# sub display_results($) {
#     my ($q) = @_;

#     my $username = $q->param('user_name');
# }

# # Outputs a web form
# sub output_form($) {
#     my ($q) = @_;
#     print $q->start_form(
#         -name => 'main',
#         -method => 'POST',
#     );

#     print $q->start_table;
#     print $q->Tr(
#       $q->td('Name:'),
#       $q->td(
#         $q->textfield(-name => "user_name", -size => 50)
#       )
#     );

#     print $q->Tr(
#       $q->td($q->submit(-value => 'Submit')),
#       $q->td('&nbsp;')
#     );
#     print $q->end_table;
#     print $q->end_form;
# }