#!/usr/bin/perl

=begin -------------------------------------------------------------------------
Compiles & emails authorised (or amended) reports as PDF attachments for
locations specified in email_contacts table, where 'type' col is set to 'report'

Required entries must be in email_contacts table (doesn't use lib/contacts.lib
as most of addresses are the same as for mdt contact), with 'type' col set to
'report'. Also requires entries in %report_status map, and %departments if
required - see config section below.

Scope = organisation, hospital or department. If set to 'organisation', records
are retrieved using parent_organisation_id; if scope set to 'department', expects
entry in %departments map to provide hospital_department.display_name to filter
on; if set to hospital, uses the referral_source_id to retrieve records

Uses LIMS::Controller::Roles::format_report() to generate PDF reports, via
LIMS::Local::Reports to provide methods - render_view(), model(), etc - required
by LIMS methods
=cut ---------------------------------------------------------------------------

use strict;
use warnings;

my $JUST_TESTING = 1; # skips history file update, emails just raj

################################################################################
use constant APP_URL => 'http://localhost:8080/hmds'; # # app address - for charts

my %departments = ( # key = email_contacts.id, value = hospital_departments.display_name
# tbl.id | display_name:
    25  => 'histopathology',
    26  => 'histopathology',
    27  => 'histopathology',
    28  => 'histopathology',
);

my %report_status = ( # key = email_contacts.id, value = new or all (diagnoses)
# tbl.id | rpt_status:
    18  => 'all',
    19  => 'all',
    20  => 'new',
    21  => 'new',
    22  => 'all',
    23  => 'all',
    24  => 'all',
    25  => 'all',
    26  => 'all',
    27  => 'all',
    28  => 'all',
);

my $delta = 1; # days ago - 1 for production
################################################################################

BEGIN {
    use FindBin qw($Bin); # warn $Bin; exit;
    use lib (
        "$Bin/../../../lib",
        '/home/raj/perl5/lib/perl5',
    );
    # override default db test:
    $ENV{ROSEDB_DEVINIT} = "$Bin/../../../config/rosedb_devinit_prod.pl";
}

use IO::All;
use Config::Auto;
use Data::Dumper;
use DateTime::Format::MySQL;

use LIMS::Local::Reports;
use LIMS::Local::ScriptHelpers;

my $cfg_file = "$Bin/../lib/settings.cfg";
my $settings = Config::Auto::parse($cfg_file); # warn Dumper $settings;
    
# get tools from LIMS::Local::ScriptHelpers:
my $tools = LIMS::Local::ScriptHelpers->new();

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

my $date = $tools->date_subtract( days => $delta )->ymd; # warn $date;
# substitutes LIMS methods required by Role::RecordHandler :
my $lims = LIMS::Local::Reports->new({tools => $tools}); 
$lims->tt_params( app_url => APP_URL ); # for charts

# common vars for email message:
my %mail = (		
	config  => $config,
);

# go:
{
    # get contents of email_contacts table:
    my $email_contacts = get_email_contacts(); # AoH
    
    # get base query, appended with restriction depending on scope (dept, hospital, organisation) 
    my $base_sql = $sql_lib->retr('mail_reports_request_ids');
    
    # get list of request_ids to send to compile_reports():
    ENTRY: # loop through each contact and get request_id's as required:
    for my $recipient (@$email_contacts) { # warn Dumper $recipient;
        next ENTRY unless $recipient->{is_active} eq 'yes';
        
        my $email_address = $recipient->{contact_address};
        my $ref_src_id    = $recipient->{referral_source_id};
        my $entry_id      = $recipient->{id}; # email_contacts.id
        my $scope         = $recipient->{scope}; # dept, hospital or organisation
        
        # copy of $base_sql initial state (gets modified inside blocks):
        my $local_sql = $base_sql;
        
        my @bind = ($date); # re-initialise with $date - universally required

        # reports can be for department, hospital or organisation:
        if ( $scope eq 'department' ) {            
            # add restrictions:
            $local_sql .= q! AND rs.id = ? AND hd.display_name = ?!;
            
            my $department = $departments{$entry_id} # warn $department;
            || die "cannot find data for email_contacts.id = $entry_id";
            
            push @bind, ($ref_src_id, $department);
        }
        elsif ( $scope eq 'organisation' ) {
            # add restrictions:
            $local_sql .= q! AND rd.parent_organisation_id = ?!;
            
            # find parent_organisation of ref_src_id:
            my $sql = q!select parent_organisation_id from referral_sources
                where id = ?!;
            $dbix->query( $sql, $ref_src_id )->into( my $parent_org_id );
            
            push @bind, $parent_org_id;            
        }
        elsif ( $scope eq 'hospital' ) {
            # add restrictions:
            $local_sql .= q! AND rs.id = ?!;
            
            push @bind, $ref_src_id;
        }
        else { die "unknown scope: $scope" }
        
        # restrict to new reports only if required:
        my $require_new_only = get_required_report_status($entry_id);        
        if ($require_new_only) { # restrict to new reports if required
            $local_sql .= q! AND rr.status = 'new'!;
        }
        
        my $request_ids = $dbix->query($local_sql, @bind)->flat;
        
        compile_reports($email_address, $request_ids) if @$request_ids;
    }
    # compile_reports('ra.jones@nhs.net', [139936]); # has chart
}

{ # tidy up cgisess files in /tmp from LIMS::Local::Reports session()
    my @files = io('/tmp')->all_files; # get all files in /tmp
    map $_->unlink, grep $_->filename =~ /\Acgisess_/, @files;
}

sub compile_reports {
    my ($email_address, $request_ids) = @_;
    
    for my $request_id (@$request_ids) { # warn $request_id;
        my $report = $lims->format_report($request_id); # L::C::Roles::RecordHandler
            # $report > io("reports/$request_id.pdf");
	
        my $data
            = $lims->model('Request')->get_referrer_department($request_id);
        
        my $referrer_department = $data->{referrer_department};
        
        my $subject = sprintf 'HMDS Report for %s / %s', 
            $referrer_department->{hospital_department}->{display_name}, # speciality
            $referrer_department->{referrer}->{name}, # referrer
        
        my $filename = sprintf '%02d_%05d.pdf',
            $data->{year} - 2000,
            $data->{request_number};

        $mail{attachment} = $report;
        $mail{recipient}  = $email_address;
        $mail{filename}   = $filename;
        $mail{subject}    = $subject; # warn Dumper \%mail;

        dispatch_report({ request_id => $request_id, message => \%mail });
    }
}

sub dispatch_report {
    my $args = shift;

    my $request_id = $args->{request_id};
    my $message    = $args->{message};
    
#    my $rtn = LIMS::Model::Email->send_attachment($message); # returns hashref:
#	if ($rtn->{success}) {
		# print "$0 reports " . lc $rtn->{message} . " to $email_address\n";

        my %data = (
            request_id => $request_id,
            recipient  => $message->{recipient},
        );
        { # log details in request_dispatch_log & request_history tables:
            my $rtn = $lims->model('Request')->update_request_dispatch_log(\%data);
            warn "Error in $0: $rtn" if $rtn;
        }
#    }
#	else {
#		warn $rtn->{message};
#        email_admin('foo');
#	}
}

sub get_email_contacts {
    my $sql = q!select * from email_contacts where type = 'report'!;
    my $email_contacts = $dbix->query($sql)->hashes; # warn Dumper $email_contacts;
    return $email_contacts;
}

sub get_required_report_status {
    my $id = shift;
    
    my $status = $report_status{$id}
    || die "cannot find data for email_contacts.id = $id";    
    return ($status eq 'new'); # returns true if report_status = 'new'
}

