#!/usr/bin/perl
use strict;
use warnings;
use File::Copy;
use ScriptLock;
use Data::Dumper;
use Time::Piece;
use File::Path;

sub diffCSV;
sub logCRM;

my $service_name = "crm_ceitec";
my $protocol_version = "3.1.0";
my $script_version = "3.0.6";

my $facility_name = $ARGV[0];
chomp($facility_name);

# create service lock
my $lock = ScriptLock->new($facility_name . "_" . $service_name);
($lock->lock() == 1) or die "Unable to get lock, service propagation was already running.";

# create send spool unless it exists
my $sendSpoolPath = "./spool/$facility_name/$service_name";
mkpath($sendSpoolPath) or die "Error creating $sendSpoolPath\n" unless -d $sendSpoolPath;

my @diff = diffCSV();

my $error = 0;

# READ FILE AND PROCESS IT
foreach my $line (@diff) {

	chomp($line);
	my @array = split(";",$line);

	my $command = "php $service_name.php";

	if (scalar(@array) < 4) {
		# Entry is probably missing login/firstName/lastName/email
		$error = 1;
		# log to stderr which is read by engine and stored in task result
		print STDERR "Not enough parameters: @array \n";
		logCRM("ERROR: Not enough parameters: @array");
		$lock->unlock();
		exit 1;
	}

	$command = $command . " --userName \"$array[0]\" --lastName \"$array[2]\" --firstName \"$array[1]\" --email \"$array[3]\"";

	if ($array[4]) {
		$command = $command . " --orgUnit \"$array[4]\"";
	} else {
		$command = $command . " --orgUnit \"\"";
	}

	if ($array[5]) {
		$command = $command . " --universityId \"$array[5]\"";
	} else {
		$command = $command . " --universityId \"\"";
	}

	if ($array[6]) {
		$command = $command . " --eppn \"$array[6]\"";
	} else {
		$command = $command . " --eppn \"\"";
	}

	if ($array[7]) {
		$command = $command . " --rgs \"$array[7]\"";
	} else {
		$command = $command . " --rgs \"\"";
	}

	if ($array[8]) {
		$command = $command . " --alternativeLoginNames \"$array[8]\"";
	} else {
		$command = $command . " --alternativeLoginNames \"\"";
	}

	my $result = `$command`;
	if ($result =~ /^ERROR/ or $result =~ /^PHP Fatal error/) {
		$error = 1;
		# log to stderr which is read by engine and stored in task result
		print STDERR $array[0] . " " . $result . "\n";
		logCRM("ERROR: " . $line);
	} else {
		logCRM("SUCCESS: " . $line);
	}

}

if ($error == 1) {
	# some entries were not updated
	print "Update ended with errors. See error log.";
	$lock->unlock();
	exit 1;
} else {
	# ended OK
	print "Update was successful.";

	# backup previous state by timestamp
	my $currentTimestamp = localtime->ymd . "-" . localtime->hms;
	copy("$sendSpoolPath/$service_name.last","./logs/$service_name.previous.".$currentTimestamp) or die "Move to backup failed: $!";
	# make new state as LAST
	copy("../gen/spool/$facility_name/$service_name/$service_name","$sendSpoolPath/$service_name.last") or die "Move new state failed: $!";
	$lock->unlock();
}
#
# DIFF previous and new state of CRM
#
sub diffCSV() {

	# Open last state file
	my $storage_file_path = "$sendSpoolPath/$service_name.last";
	open my $storage_file, $storage_file_path or die "Could not open $storage_file_path: $!";

	# Open new gen file
	my $gen_file_path = "../gen/spool/$facility_name/$service_name/$service_name";
	open my $gen_file, $gen_file_path or die "Could not open $gen_file_path: $!";

	my %previous_state;
	my %current_state;
	my @diff;

	while(<$storage_file>) {
		chomp($_);
		$_ =~ /^([^;]*);/;
		my $login = $1;
		$previous_state{$login} = $_;
	}

	while(<$gen_file>) {
		chomp($_);
		$_ =~ /^([^;]*);/;
		my $login = $1;
		$current_state{$login} = $_;
		push @diff, $_ unless defined $previous_state{$login} && $previous_state{$login} eq $_;
	}

	close $storage_file;
	close $gen_file;

	my $currentTimestamp = localtime->ymd . "-" . localtime->hms;
	my $dest_fname_new = "/tmp/$service_name.new.".$currentTimestamp;
	my $dest_fname_prev = "/tmp/$service_name.last.".$currentTimestamp;

	my $keynumber = keys %previous_state;
	if ($keynumber < 1) {
		print "Previous state was empty! Exiting! See:\n$dest_fname_new\n$dest_fname_prev";
		copy("$sendSpoolPath/$service_name.last",$dest_fname_prev) or die "Move to /tmp backup failed: $!";
		copy($gen_file_path,$dest_fname_new) or die "Move to /tmp backup failed: $!";
		$lock->unlock();
		exit 1;
	}

	my $keynumber_new = keys %current_state;
	if ($keynumber_new < 1) {
		print "Current state is empty! Exiting! See:\n $dest_fname_new \n $dest_fname_prev";
        copy("$sendSpoolPath/$service_name.last",$dest_fname_prev) or die "Move to /tmp backup failed: $!";
		copy($gen_file_path,$dest_fname_new) or die "Move to /tmp backup failed: $!";
		$lock->unlock();
		exit 1;
	}

	if (@diff > 800) {
		copy("$sendSpoolPath/$service_name.last",$dest_fname_prev) or die "Move to /tmp backup failed: $!";
		copy($gen_file_path,$dest_fname_new) or die "Move to /tmp backup failed: $!";
		print "Updating more than 800 entries! Exiting for safety!\n";
		logCRM("--- Would update ---\n" . Dumper(\@diff));
		$lock->unlock();
		exit 1;
	}

	# actually "to be removed"
	for my $login (sort keys %previous_state) {
		unless (defined $current_state{$login}) {
			# clear groups (rgs) from previous entry -> remove from CRM
			my $line = $previous_state{$login};
			my @array = split(";",$line);
			@array[7] = "";
			$line = join(";",@array);
			push(@diff, $line);
		}
	}

	return @diff;

}

#
# Log any message to log file located in same folder as the script.
# Each message starts at new line with a date.
#
sub logCRM() {
	my $message = shift;
	open(LOGFILE, ">>./logs/crm_ceitec.log");
	print LOGFILE (localtime(time) . ": " . $message . "\n");
	close(LOGFILE);
}
