#!/usr/bin/env perl

=begin -------------------------------------------------------------------------
requests requiring confirmation of diagnosis (see .local/diagnosis_confirm.yml):

1) request is authorised
2) has no outstanding tests
3) request.status <> 'complete'
4) has a cytogenetics, molecular or FISH results summary timestamp AFTER auth date

confirmation of diagnosis NOT required if screened as:
	Rheumatoid arthritis / Rituximab (RA) monitoring
	Molecular miscellaneous
	Roche Gallium trial
	Chimerism sample
	PNH / PNH (PB)
  OR:
	CML follow-up on PB sample
	CMPD pres & follow-up on PB sample with JAK2 as sole test

Also sets request status to complete if status = authorised, has no outstanding
tests and NOT in incomplete_requests list ie requiring diagnosis confirmation
=cut ---------------------------------------------------------------------------

use strict;
use warnings;

my $JUST_TESTING = 0; # dumps HTML file to $Bin/incomplete.html; no emails or db update

################################################################################
my @recipients = qw( hmds.secure ); # raj sinclair douglas bagguley oconnor
################################################################################

use lib '/home/raj/perl5/lib/perl5';

use IO::All;
use Data::Printer;
use DateTime::Format::MySQL;

use FindBin qw($Bin); # warn $Bin;
use lib "$Bin/../../../lib";

use LIMS::Local::ScriptHelpers;

# get tools from LIMS::Local::ScriptHelpers:
my $tools = LIMS::Local::ScriptHelpers->new();
$tools->test_only($JUST_TESTING);

my $sql_lib = $tools->sql_lib();
my $config  = $tools->config();
my $dbix    = $tools->dbix();

my $yaml = $tools->get_yaml_file('diagnosis_confirm'); # p $yaml; exit;
my $dfm  = DateTime::Format::MySQL->new();

my $excluded_screens = $yaml->{exempt_all_sample_types}; # p $excluded_screens;

my $template  = 'cron/incomplete_requests.tt';
my $dump_file = "$Bin/incomplete.html"; # for use if JUST_TESTING
# reset dump_file:
io($dump_file)->unlink if -e $dump_file;

# sql for REQUEST block:
my %SQL_FOR = (
    results_summary => $sql_lib->retr('incomplete_requests_results_summary'),
	request_report  => $sql_lib->retr('incomplete_requests_request_report'),
    initial_screen  => $sql_lib->retr('incomplete_requests_initial_screen'),
    request_ids     => $sql_lib->retr('incomplete_requests_request_ids'),
    lab_tests       => $sql_lib->retr('incomplete_requests_lab_tests'),
    specimen        => $sql_lib->retr('incomplete_requests_specimen'),
); # p %SQL_FOR;

# get list of request_ids where request authorised, status incomplete and have
# molecular, cytogenetic or FISH result summary:
my $request_ids = _get_request_ids(); # p scalar @$request_ids; # arrayref

my (%h, @ids);

REQUEST:
for my $id (@$request_ids) { # p $id;  next unless $id == 241124;
	# data for determining whether diagnosis confirmation is required:
	my $args = {
		specimen => [], # array(ref) of sample_codes
		lab_test => [], # AoH (keys = test_name & status)
		section  => [], # array(ref) of lab_section names
		screen   => undef, # str
		yaml     => $yaml,
	};

	# get initial_screen:
	$dbix->query( $SQL_FOR{initial_screen}, $id )->into( $args->{screen} );

	# get specimen(s) array(ref):
	$args->{specimen} = $dbix->query( $SQL_FOR{specimen}, $id )->flat;

	# get lab_tests (AoH):
	$args->{lab_test} = $dbix->query( $SQL_FOR{lab_tests}, $id )->hashes;

	{ # get results_summary section names => result_summary timestamp (AoH):
        my $sql = $SQL_FOR{results_summary}; # p [$sql, $id];
		my $sections = $dbix->query( $sql, $id )->hashes;
		# convert mysql datetime to datetime object:
		$_->{time} = $dfm->parse_datetime($_->{time}) for @$sections;
		$args->{section} = $sections;
	}

	# get report data:
	my $req = $dbix->query( $SQL_FOR{request_report}, $id )->hash;

	# add authorisation date (as dt object) for comparison to result summary date:
	$args->{authorisation_date} = $dfm->parse_datetime($req->{auth_date});

	# next request if diagnosis confirmation NOT required:
	next REQUEST unless $tools->diagnosis_confirmation_required($args);

    my $reporter = $req->{report_by};
	push @{ $h{$reporter} }, $req;

	next REQUEST if $JUST_TESTING; # don't need @ids - for use in updating db

    # add to @ids for use in query as 'NOT IN':
    push @ids, $id; # ie diagnosis confirmation IS required
} # p %h; p @ids;

my %mail = ( config  => $config, content => 'html' );

# email messages:
REPORTER:
while ( my($reporter, $d) = each %h ) {
    my %tt_params = ( reporter => $reporter, data => $d );
    my $msg = $tools->process_template($template, \%tt_params);
### uncomment next line to dump to file and NOT send email:
	# $msg >> io("$Bin/incomplete.html"); next REPORTER; die;

    $mail{message} = $msg; # p $msg; next REPORTER;
    $mail{subject} =
		sprintf 'HILIS records requiring confirmation of diagnosis on %s [%s]',
			$tools->time_now->dmy, uc $reporter;

    $JUST_TESTING # dump to file only if just testing
        ? $msg >> io("$Bin/incomplete.html")
        : $tools->send_mail(\%mail, \@recipients);
}

set_request_status() unless $JUST_TESTING; # don't want to update db if just testing

#===============================================================================

sub set_request_status { # warn 'here'; # die;
	# status_option.id of 'complete' requests:
	my $status_option_id = _complete_status_option_id();
	# server username:
	my $server_user = $tools->get_server_user_details(); # p $server_user;

	# get list of requests where status = authorised and do NOT require diagnosis
	# confirmation (using @ids to supply requests where confirmation IS required):
	my $authorised_requests = _get_authorised_requests(\@ids); # p $authorised_requests;

	DATA: # skip any requests with outstanding tests - set rest to status = complete:
	for my $data( @$authorised_requests ) { # p $data;
		my $lab_test = $dbix->query( $SQL_FOR{lab_tests}, $data->{id} )->hashes;
		my @status = map $_->{status}, @$lab_test; # p @status;

		next DATA if grep $_ ne 'complete', @status; # skip if ANY test status NOT complete

		{ # now have authorised case with no outstanding lab-tests and not requiring a
		  # diagnosis confirmation, so set request status to 'complete':
			my %h = (
				status_option_id => $status_option_id,
				# preserve timestamp to avoid triggering unnecessary report:
				updated_at => $data->{updated_at},
			); # p $data->{id};
			$dbix->update( 'requests', \%h, { id => $data->{id} } );
		}
		{ # log action in request_history:
			my %data = (
				request_id 	=> $data->{id},
				user_id 	=> $server_user->{id},
				action 		=> 'set request status to complete',
			); # p %data;
			$dbix->insert('request_history', \%data);
		}
	}
}

sub _get_request_ids {
    my $sql = $SQL_FOR{request_ids}; # p $sql;
    my $request_ids = $dbix->query($sql, @$excluded_screens)->flat; # p $request_ids;
    return $request_ids;
}

sub _get_authorised_requests {
    my $ids = shift; # p $ids;
=begin
SELECT t1.id, t1.updated_at
FROM requests t1
    JOIN status_options t2 ON (t1.status_option_id = t2.id)
WHERE t2.description = 'authorised'
    and t1.id NOT IN (??)
=cut
	# if $ids arrayref empty, query dies, so ensure it isn't:
	push @$ids, 0 if not @$ids; # p $ids; # ie t1.id NOT IN (0)

    my $sql = $sql_lib->retr('authorised_requests'); # p $sql;
    my $requests = $dbix->query($sql, @$ids)->hashes; # p $requests;
    return $requests;
}

sub _complete_status_option_id {
    $dbix->select('status_options', 'id',
		{ description => 'complete' })->into(my $id); # p $id;
    return $id;
}
