package LIMS::Controller::PrintRun;

use base 'LIMS::Base';
use LIMS::Local::Utils;
use Data::Dumper;

use Moose;
with (
    'LIMS::Controller::Roles::DataMap',
    'LIMS::Controller::Roles::RecordHandler',
	'LIMS::Controller::Roles::ResultHandler',
);

has reports => (
    is      => 'ro',
    isa     => 'ArrayRef[Str]',
    default => sub { [] },
    lazy    => 1,
	traits  => ['Array'],
	handles => {
		add_to_reports => 'push',
	},
);
__PACKAGE__->meta->make_immutable(inline_constructor => 0);

#-------------------------------------------------------------------------------
sub default : StartRunmode {
    my $self = shift;

	return $self->forbidden() unless $self->user_can('print_all');
    
    my $last_working_day = $self->_get_last_working_day();
    $self->tt_params( date => $last_working_day );

    return $self->tt_process();
}

#-------------------------------------------------------------------------------
sub do : Runmode {
    my $self = shift;
    
    # get start & end datetime objects:
    my $start = $self->_get_start_date; # warn Dumper $start;
    my $end   = $self->_get_end_date;   # warn Dumper $end;

    # get request id's for records amended between start & end datetimes:
    my $request_ids
        = $self->model('Request')->get_print_run_request_ids($start, $end);

    unless (@$request_ids) {
        $self->flash( info => $self->messages('search')->{no_records_found} );
        return $self->redirect( $self->query->url . '/printrun' );
    }

	# allowed report error_codes:
	my $report_error_codes = $self->report_error_codes_map;
    # diagnosis_context_warnings:
	my $context_warning = $self->diagnosis_context_warning_map;

	# preserve 'app_url' & 'active_link' tt_params for use in loop:
	my %required_tt_params = map {
		$_ => $self->tt_params->{$_};
	} qw(app_url active_link);

	# my $i;
    foreach my $request_id (@$request_ids) { # last if $i++ > 1; # for testing
        # format request data for template:
        $self->format_print_record_request_data($request_id);
        # add data maps for template:
		$self->tt_params(
            context_warning_map => $context_warning,
            report_error_codes  => $report_error_codes,
        );
        # render template & add to 'reports' attr:
        my $html = $self->render_view('record/body.tt');
        $self->add_to_reports($$html); # dereference first
        
        { # has copy_to been requested?
            my $request_options = $self->stash->{request_data}->{request_options};
            # warn Dumper $request_options;
            if ( $request_options->{copy_to}->{is_selected} ) {
                my $cc = $self->_generate_copy($html);
                $self->add_to_reports($cc); # already deref'ed
            }
        }
        $self->tt_clear_params; # clear all template params for next loop
		$self->tt_params(\%required_tt_params); # add required ones back
    }
    
    return $self->tt_process({ reports => $self->reports });
}

#-------------------------------------------------------------------------------
sub _generate_copy {
    my ($self, $tmpl_ref) = @_;
    
    my $html = ${$tmpl_ref}; # de-reference tmpl var
    
    # replace 'Referrer' with 'Copy to':
    $html =~ s/Referrer: .*(<br \/>)/<span style="color: #f00">Copy to:<\/span> $1/;
    
    return $html;
}

#-------------------------------------------------------------------------------
sub _get_start_date {
    my $self = shift;
    
    my $q = $self->query;

    my $datetime;
    
    # expect params 'last_working_day' OR 'date', and optional 'today':
    if ( $q->param('last_working_day') ) {
        $datetime = $self->_get_last_working_day();
    }
    elsif ( my $date = $q->param('date') ) {
        $datetime = LIMS::Local::Utils::to_datetime_using_datecalc($date)
        || return $self->error("cannot decode date-string $date");
    } # warn Dumper $datetime;

    # in case start date not supplied:
    $datetime ||= DateTime->today(); # beginning of day (00:00:00)
    
    return $datetime;    
}

#-------------------------------------------------------------------------------
sub _get_end_date {
    my $self = shift;
   
    my $datetime = $self->query->param('today')
        ? DateTime->now(time_zone => 'local') # up to current time (BST-aware)
        : DateTime->today(); # beginning of day (00:00:00)

    return $datetime;
}

#-------------------------------------------------------------------------------
sub _get_last_working_day { # doesn't consider public holidays
    my $self = shift;
    
    my $dt = DateTime->today->subtract( days => 1 ); # yesterday at 00:00:00

    # day 6 is Saturday, day 7 is Sunday
    while ( $dt->day_of_week >= 6 ) {
        $dt->subtract( days => 1 );
    } # warn Dumper $dt;
    
    return $dt;
}

1;