package LIMS::Controller::HMRN::Data;

use Moose;
with (
    'LIMS::Controller::Roles::Misc', # redirect_after_edit_success()
    'LIMS::Controller::Roles::FormData', # validate_form_params()
);
BEGIN { extends 'LIMS::Base'; }
__PACKAGE__->meta->make_immutable(inline_constructor => 0);

use Data::Dumper;

#__PACKAGE__->authz->authz_runmodes(	':all' => 'view_clinical_data' );

# ------------------------------------------------------------------------------
# default() should never be called direct - redirect to start page:
sub default : StartRunmode {
    my $self = shift; $self->_debug_path($self->get_current_runmode);
    return $self->redirect( $self->query->url );
}

# ------------------------------------------------------------------------------
sub load : Runmode { # initial point of entry ie /hmrn_data/=/nnn
    return shift->forward('hmrn'); # just forward
}

# ------------------------------------------------------------------------------
sub hmrn : Runmode {
    my $self = shift; $self->_debug_path($self->get_current_runmode);
    my $errs = shift; # $self->stash( errs => $errs ); # for debugging in tmpl

    return $self->forbidden() unless $self->user_can('view_clinical_data');

    my $request_id = $self->param('id')
    || return $self->error('no id passed to '.$self->get_current_runmode);
    
    # get request data:
    my $request_data
        = $self->model('Request')->get_single_request($request_id);
    $self->tt_params( request_data => $request_data );
    
    my $patient_id = $request_data->patient_case->patient_id;

    { # get request history:
        my $history = $self->model('History')->get_request_history($request_id);
        # create hash with keys = action & values = associated history object:
        my %request_history = map { $_->action => $_ } @$history;
        $self->tt_params( request_history => \%request_history );
    }
    { # get patient demographic data:        
        my $demographics
            = $self->model('HMRN')->get_patient_demographics($patient_id);
        
        if ( $demographics ) {
            my $demographic_data = $demographics->as_tree;
            { # add post-code at diagnosis:
                my $post_code_at_diagnosis
                    = $self->model('HMRN')->get_post_code_at_diagnosis($patient_id);
                $demographic_data->{post_code_at_diagnosis}
                    = $post_code_at_diagnosis;
            }
            $self->tt_params( demographic_data => $demographic_data );
            
            # list of GP's for practice if exists:
            if ( my $practice_id = $demographics->practice_id ) {         
                my $GPs = $self->model('Outreach') # same requirement in Outreach model
                    ->get_practitioners_for_practice($practice_id);
                $self->tt_params( practice_gps => $GPs );
            
                # get unknown practitioner id:
                my $o = LIMS::DB::ReferralType
                    ->new(description => 'practitioner')
                    ->load(with => 'unknown_referrer'); # warn Dumper $o->unknown_referrer;
                $self->tt_params( unknown_gp_id => $o->unknown_referrer->id); 
            }
        }
    }
    {  # get hmrn data:
        my $vars = $self->query->Vars();
        my %args = (
            patient_id => $patient_id,
            vars       => $vars || {}, # might be required if validation fails
        );
        my $hmrn_data = $self->model('HMRN')->get_all_hmrn_data(\%args);
        
        # is patient also in outreach (can't edit GP practice if so):
        if ($self->cfg('settings')->{have_outreach}) {
            my $in_outreach = $self->model('HMRN')->is_in_outreach($patient_id);
            $hmrn_data->{is_in_outreach} = $in_outreach;
        }
        $self->tt_params( hmrn_data => $hmrn_data );
    }	
    { # validation profiles for param data:
        my %validation_profile = ();
        
        my $param_constraints = $self->model('HMRN')->get_parameter_constraints;
        $validation_profile{constraints} = $param_constraints;
        
        for my $type( qw/lymphoid myeloid precursor plasmacell/ ) {
            my $profile = $self->validate('hmrn_'.$type); # warn Dumper $profile;
            my %required = map { $_ => 1 } @{ $profile->{required} };
            $validation_profile{required_fields}{$type} = \%required;
        }
        $self->tt_params( validation_profile => \%validation_profile );
    }

    # provide an age calculation callback:
    $self->tt_params( calculate_age => sub {
        LIMS::Local::Utils::calculate_age(@_);
    });
    
    return $self->tt_process($errs);
}

# ------------------------------------------------------------------------------
# handles all lymphoid, myeloid, precursor & plasma-cell data, expects hidden param 'data_set':
sub edit : Runmode {
    my $self = shift; $self->_debug_path($self->get_current_runmode);
    
    return $self->forbidden() unless $self->user_can('edit_clinical_data');
    
    my $data_type = $self->query->param('data_set')
    || return $self->error('no data_set type passed to '.$self->get_current_runmode);
    
    my $profile = $self->validate('hmrn_'.$data_type); # warn Dumper $profile;

    my $dfv = $self->check_rm( 'hmrn', $profile )
    || return $self->dfv_error_page;

    my $request_id = $self->param('id')
    || return $self->error('no request_id passed to '.$self->get_current_runmode);
    
    my $patient_id = $self->param('Id')
    || return $self->error('no patient_id passed to '.$self->get_current_runmode);
    
    my $data = $dfv->valid; # warn Dumper $data;
    
    my %args = (
        data => $data,
        data_type => $data_type,
        patient_id => $patient_id,
    );
    
    my $rtn = $self->model('HMRN')->update_params(\%args);
    return $rtn
        ? $self->error($rtn)
        : $self->redirect_after_edit_success('/hmrn_data/=/' . $request_id);
}

# ------------------------------------------------------------------------------
sub comment : Runmode {
    my $self = shift; $self->_debug_path($self->get_current_runmode);
    
    return $self->forbidden() unless $self->user_can('edit_clinical_data');

    my $request_id = $self->param('id')
    || return $self->error('no request_id passed to '.$self->get_current_runmode);
    
    my $patient_id = $self->param('Id')
    || return $self->error('no patient_id passed to '.$self->get_current_runmode);
    
    my $data = $self->query->Vars(); # only single param passed - 'comment'
    $data->{patient_id} = $patient_id;
    
    my $rtn = $self->model('HMRN')->update_comment($data);
    return $rtn
        ? $self->error($rtn)
        : $self->redirect_after_edit_success('/hmrn_data/=/' . $request_id);    
}

# ------------------------------------------------------------------------------
sub view_history : Runmode {
    my $self = shift; $self->_debug_path($self->get_current_runmode);
    
    return $self->forbidden() unless $self->user_can('edit_clinical_data');

    my $patient_id = $self->param('id')
    || return $self->error('no patient_id passed to '.$self->get_current_runmode);
    
    my $data = $self->model('HMRN')->get_history($patient_id);
    $self->tt_params( data => $data );
    return $self->tt_process();
}

# ------------------------------------------------------------------------------
sub edit_demographics : Runmode {
    my $self = shift; $self->_debug_path($self->get_current_runmode);
    
    return $self->forbidden() unless $self->user_can('edit_clinical_data');

    my $dfv = $self->check_rm( 'hmrn', $self->validate('hmrn_demographics') )
    || return $self->dfv_error_page;

    my $request_id = $self->param('id')
    || return $self->error('no request_id passed to '.$self->get_current_runmode);
    
    my $patient_id = $self->param('Id')
    || return $self->error('no patient_id passed to '.$self->get_current_runmode);
    
    my $data = $dfv->valid;
    # add patient_id:
    $data->{patient_id} = $patient_id; # warn Dumper $data; 

    # first update patient_demographics table:
    my $rtn = $self->model('Patient')->update_patient_demographics($data);
    return $self->error($rtn) if $rtn;
    
    # now update hmrn.patient_post_code table (ie value at diagnosis):
    if ( $data->{post_code} ) { # only have access if patient NOT in Outreach:
        $rtn = $self->model('HMRN')->update_post_code_at_diagnosis($data);

        return $rtn
            ? $self->error($rtn)
            : $self->redirect_after_edit_success('/hmrn_data/=/' . $request_id);
    }
}

# ------------------------------------------------------------------------------
# edit post-code at diagnosis - only necessary if patient in Outreach & post-code
# originally entered incorrectly:
sub edit_post_code : Runmode {
    my $self = shift; $self->_debug_path($self->get_current_runmode);
    
    return $self->forbidden() unless $self->user_can('edit_clinical_data');

    my $request_id = $self->param('id') || $self->query->param('request_id')
    || return $self->error('no request_id passed to '.$self->get_current_runmode);
    
    my $patient_id = $self->param('Id') || $self->query->param('patient_id')
    || return $self->error('no patient_id passed to '.$self->get_current_runmode);
    
    # submitted via url to request edit page:
    my $post_code_at_diagnosis = $self->query->param('post_code_at_diagnosis');
    # submitted via form to update post-code:
    my $post_code = $self->query->param('post_code');

    if ($post_code) { # assume edit submission - doesn't permit blank submission:
        # just make sure it's valid:
        my $profile = $self->validate('hmrn_demographics');
        my $dfv = $self->validate_form_params($profile); 
        if ($dfv->has_invalid) { # $dfv->has_missing not req'd - wouldn't get here
            $self->tt_params(dfv_err => $dfv->msgs); # warn Dumper $dfv->msgs;
            return $self->fill_form($self->tt_process);
        }
        
        my %data = (
            patient_id => $patient_id,
            post_code  => $post_code,
        );
        my $rtn = $self->model('HMRN')->update_post_code_at_diagnosis(\%data);
        return $rtn
            ? $self->error($rtn)
            : $self->redirect_after_edit_success('/hmrn_data/=/' . $request_id);
    }
    else { # assume new request for edit:
        return $self->tt_process({ post_code => $post_code_at_diagnosis });
    }
    # else { # need to send null post-code to tt_process() for new entry
    #    return $self->error('no post-code value submitted');
    # }
}

# ------------------------------------------------------------------------------
sub edit_event_data : Runmode {
    my $self = shift; $self->_debug_path($self->get_current_runmode);
    
    return $self->forbidden() unless $self->user_can('edit_clinical_data');

    my $dfv = $self->check_rm( 'hmrn', $self->validate('hmrn_chronologies') )
    || return $self->dfv_error_page;

    my $request_id = $self->param('id')
    || return $self->error('no request_id passed to '.$self->get_current_runmode);
    
    my $patient_id = $self->param('Id')
    || return $self->error('no patient_id passed to '.$self->get_current_runmode);

    my $data = $dfv->valid;
    
    # add patient_id:
    $data->{patient_id} = $patient_id;
    
    my $rtn = $self->model('HMRN')->update_patient_events($data);
    return $rtn
        ? $self->error($rtn)
        : $self->redirect_after_edit_success('/hmrn_data/=/' . $request_id);   
}

# ------------------------------------------------------------------------------
sub edit_antecedent : Runmode {
    my $self = shift; $self->_debug_path($self->get_current_runmode);
    
    return $self->forbidden() unless $self->user_can('edit_clinical_data');

    my $request_id = $self->param('id')
    || return $self->error('no request_id passed to '.$self->get_current_runmode);
    
    my $patient_id = $self->param('Id')
    || return $self->error('no patient_id passed to '.$self->get_current_runmode);

    my $vars = $self->query->Vars;

    # add patient_id:
    $vars->{patient_id} = $patient_id;
    
    my $rtn = $self->model('HMRN')->update_antecedent_events($vars);
    return $rtn
        ? $self->error($rtn)
        : $self->redirect_after_edit_success('/hmrn_data/=/' . $request_id);
}

# ------------------------------------------------------------------------------
sub new_treatment : Runmode {
    my $self = shift; $self->_debug_path($self->get_current_runmode);
    
    return $self->forbidden() unless $self->user_can('edit_clinical_data');

    my $dfv = $self->check_rm( 'hmrn', $self->validate('hmrn_treatment') )
    || return $self->dfv_error_page;

    my $request_id = $self->param('id')
    || return $self->error('no request_id passed to '.$self->get_current_runmode);
    
    my $patient_id = $self->param('Id') 
    || return $self->error('no patient_id passed to '.$self->get_current_runmode);    
    
    my $data = $dfv->valid();

    # add patient_id:
    $data->{patient_id} = $patient_id;
    
    my $rtn = $self->model('HMRN')->new_treatment_data($data);
    return $rtn
        ? $self->error($rtn)
        : $self->redirect_after_edit_success('/hmrn_data/=/' . $request_id);
}

# ------------------------------------------------------------------------------
sub referral_pathway : Runmode {
    my $self = shift; $self->_debug_path($self->get_current_runmode);
    
    return $self->forbidden() unless $self->user_can('edit_clinical_data');

    my $dfv = $self->check_rm( 'hmrn', $self->validate('hmrn_referral') )
    || return $self->dfv_error_page;

    my $request_id = $self->param('id')
    || return $self->error('no request_id passed to '.$self->get_current_runmode);
    
    my $patient_id = $self->param('Id') 
    || return $self->error('no patient_id passed to '.$self->get_current_runmode);    
    
    my $data = $dfv->valid();

    # add patient_id:
    $data->{patient_id} = $patient_id; # warn Dumper $data;
    
    my $rtn = $self->model('HMRN')->new_referral_data($data);
    return $rtn
        ? $self->error($rtn)
        : $self->redirect_after_edit_success('/hmrn_data/=/' . $request_id);
}

# ------------------------------------------------------------------------------
sub new_imaging_data : Runmode {
    my $self = shift; $self->_debug_path($self->get_current_runmode);
    
    return $self->forbidden() unless $self->user_can('edit_clinical_data');

    my $dfv = $self->check_rm( 'hmrn', $self->validate('hmrn_imaging') )
    || return $self->dfv_error_page; # warn Dumper $dfv;

    my $request_id = $self->param('id')
    || return $self->error('no request_id passed to '.$self->get_current_runmode);
    
    my $patient_id = $self->param('Id') 
    || return $self->error('no patient_id passed to '.$self->get_current_runmode);    
    
    my $data = $dfv->valid();

    # add patient_id:
    $data->{patient_id} = $patient_id;
    
    my $rtn = $self->model('HMRN')->new_imaging_data($data);
    return $rtn
        ? $self->error($rtn)
        : $self->redirect_after_edit_success('/hmrn_data/=/' . $request_id);    
}

# ------------------------------------------------------------------------------
sub edit_imaging : Runmode {
    my $self = shift; $self->_debug_path($self->get_current_runmode);
    my $errs = shift; # $self->stash( errs => $errs );
    
    return $self->forbidden() unless $self->user_can('edit_clinical_data');

    my $request_id = $self->param('id')
    || return $self->error('no request_id passed to '.$self->get_current_runmode);
    
    my $event_id = $self->param('Id') # 
    || return $self->error('no event id passed to '.$self->get_current_runmode);    

    { # imaging data for requested scan:
        my $data = $self->model('HMRN')->get_imaging_data($event_id);
        # put request_id into $data:
        $data->{request_id} = $request_id;
    
        $self->tt_params(data => $data);
    }
    { # imaging_options :
        my $opts = $self->model('HMRN')->get_imaging_options;
        $self->tt_params(imaging_opts => $opts);
    }
    return $self->tt_process($errs);
}

# ------------------------------------------------------------------------------
sub do_edit_imaging : Runmode {
    my $self = shift; $self->_debug_path($self->get_current_runmode);
    
    return $self->forbidden() unless $self->user_can('edit_clinical_data');

    my $request_id = $self->param('id')
    || return $self->error('no request_id passed to '.$self->get_current_runmode);
    
    my $event_id = $self->param('Id') # event table 'id'
    || return $self->error('no event id passed to '.$self->get_current_runmode);    

    my $dfv = $self->check_rm( 'edit_imaging', $self->validate('hmrn_imaging') )
    || return $self->dfv_error_page;
    
    my $data = $dfv->valid(); # warn Dumper $data;
    # put event table 'id' into $data:
    $data->{event_id} = $event_id; # warn Dumper $data;

    my $rtn = $self->model('HMRN')->update_imaging_data($data);
    $self->flash( info => $self->messages('action')->{edit_success} ) if ! $rtn;        

    return $rtn
        ? $self->error($rtn)
        : $self->redirect( $self->query->url . '/hmrn_data/=/' . $request_id );
}

# ------------------------------------------------------------------------------
sub edit_referral : Runmode {
    my $self = shift; $self->_debug_path($self->get_current_runmode);
    my $errs = shift;
    
    return $self->forbidden() unless $self->user_can('edit_clinical_data');

    my $request_id = $self->param('id')
    || return $self->error('no request_id passed to '.$self->get_current_runmode);
    
    my $tbl_id = $self->param('Id') # patient_referral table 'id'
    || return $self->error('no id passed to '.$self->get_current_runmode);    
    
    my $data = $self->model('HMRN')->get_referral_data($tbl_id);
    # put request_id into $data:
    $data->{request_id} = $request_id;
    $self->tt_params(data => $data);
    
    # for jquery validation (date functions don't work with DatePicker):
    # $self->tt_params( profile_name => 'hmrn_referral' );
    
    return $self->tt_process($errs);
}

# ------------------------------------------------------------------------------
sub do_edit_referral : Runmode {
    my $self = shift; $self->_debug_path($self->get_current_runmode);
    
    return $self->forbidden() unless $self->user_can('edit_clinical_data');

    my $request_id = $self->param('id')
    || return $self->error('no request_id passed to '.$self->get_current_runmode);
    
    my $tbl_id = $self->param('Id') # table 'id'
    || return $self->error('no id passed to '.$self->get_current_runmode);    

    my $rtn;
    
    if ( $self->query->param('delete') ) {
        return $self->forward('edit_referral')
            unless $self->query->param('confirm_delete');
        $rtn = $self->model('HMRN')->delete_referral_data($tbl_id); # just send id for del
        $self->flash( info => $self->messages('action')->{delete_success} ) if ! $rtn;        
    }
    else {
        my $dfv = $self->check_rm( 'edit_referral', $self->validate('hmrn_referral') )
        || return $self->dfv_error_page;
    
        my $data = $dfv->valid();
        # put treatment table 'id' into $vars:
        $data->{id} = $tbl_id; # warn Dumper $data;
        
        $rtn = $self->model('HMRN')->update_referral_data($data);
        $self->flash( info => $self->messages('action')->{edit_success} ) if ! $rtn;        
    }
    
    return $rtn
        ? $self->error($rtn)
        : $self->redirect( $self->query->url . '/hmrn_data/=/' . $request_id);
}

# ------------------------------------------------------------------------------
sub edit_treatment : Runmode {
    my $self = shift; $self->_debug_path($self->get_current_runmode);
    my $errs = shift;
    
    return $self->forbidden() unless $self->user_can('edit_clinical_data');

    my $request_id = $self->param('id')
    || return $self->error('no request_id passed to '.$self->get_current_runmode);
    
    my $treatment_id = $self->param('Id') # treatment table 'id'
    || return $self->error('no id passed to '.$self->get_current_runmode);    
    
    my $data = $self->model('HMRN')->get_treatment_data($treatment_id);
    # put request_id into $data:
    $data->{request_id} = $request_id;
    $self->tt_params(data => $data);
    
    # for jquery validation (date functions don't work with DatePicker):
    # $self->tt_params( profile_name => 'hmrn_treatment' );
    
    return $self->tt_process($errs);
}

# ------------------------------------------------------------------------------
sub do_edit_treatment : Runmode {
    my $self = shift; $self->_debug_path($self->get_current_runmode);
    
    return $self->forbidden() unless $self->user_can('edit_clinical_data');

    my $request_id = $self->param('id')
    || return $self->error('no request_id passed to '.$self->get_current_runmode);
    
    my $treatment_id = $self->param('Id') # treatment table 'id'
    || return $self->error('no id passed to '.$self->get_current_runmode);    

    my $rtn;
    
    if ( $self->query->param('delete') ) {
        return $self->forward('edit_treatment')
            unless $self->query->param('confirm_delete');
        $rtn = $self->model('HMRN')->delete_treatment_data($treatment_id); # just send id for del
        $self->flash( info => $self->messages('action')->{delete_success} ) if ! $rtn;        
    }
    else {
        my $dfv = $self->check_rm( 'edit_treatment', $self->validate('hmrn_treatment') )
        || return $self->dfv_error_page;
    
        my $data = $dfv->valid();
        # put treatment table 'id' into $vars:
        $data->{id} = $treatment_id; # warn Dumper $data;
        
        $rtn = $self->model('HMRN')->update_treatment_data($data);
        $self->flash( info => $self->messages('action')->{edit_success} ) if ! $rtn;        
    }
    
    return $rtn
        ? $self->error($rtn)
        : $self->redirect( $self->query->url . '/hmrn_data/=/' . $request_id);
}

# ------------------------------------------------------------------------------
sub edit_mdt_date : Runmode {
    my $self = shift; $self->_debug_path($self->get_current_runmode);
    
    return $self->forbidden() unless $self->user_can('edit_clinical_data');

    my $request_id = $self->param('id')
    || return $self->error('no request_id passed to '.$self->get_current_runmode);
    
    my $id = $self->param('Id')
    || return $self->error('no id passed to '.$self->get_current_runmode);    
    
    my $vars = $self->query->Vars();
    
    my $rtn;
    
    # for jquery validation (does't work with DatePicker):
    # $self->tt_params( profile_name => 'hmrn_mdt_date' );

    # deletion request:
    if ($vars->{delete}) { # NB: do this 1st as var 'date' also passed  
        return $self->fill_form($self->tt_process) # require confirmation before deleting:
            unless $self->query->param('confirm_delete');
        $rtn = $self->model('HMRN')->delete_mdt_date($id); # just send id for del
        $self->flash( info => $self->messages('action')->{delete_success} ) if ! $rtn;
    }
    # if revised date submitted:
    elsif ($vars->{date}) {
        # validate date:
        my $profile = $self->validate('hmrn_mdt_date');
        my $dfv = $self->validate_form_params($profile); 
        if ($dfv->has_invalid) { # $dfv->has_missing not req'd - wouldn't get here
            $self->tt_params(dfv_err => $dfv->msgs); # warn Dumper $dfv->msgs;
            return $self->fill_form($self->tt_process);
        }

        $vars->{id} = $id; # add row id for update
        $rtn = $self->model('HMRN')->update_mdt_date($vars);   
        $self->flash( info => $self->messages('action')->{edit_success} ) if ! $rtn;
    }
    else { # 1st call to method (just get data):
        my $data = $self->model('HMRN')->get_mdt_data($id);
        return $self->tt_process({ data => $data });
    }
    
    return $rtn
        ? $self->error($rtn)
        : $self->redirect( $self->query->url . '/hmrn_data/=/' . $request_id);
}

# ------------------------------------------------------------------------------
sub edit_practice : Runmode {
    my $self = shift; $self->_debug_path($self->get_current_runmode);
    
    return $self->forbidden() unless $self->user_can('edit_clinical_data');

    my $request_id = $self->param('id')
    || return $self->error('no request_id passed to '.$self->get_current_runmode);
    
    my $patient_id = $self->param('Id')
    || return $self->error('no patient_id passed to '.$self->get_current_runmode);
    
    # if new practice_id submitted:
    if ( my $practice_id = $self->query->param('practice_id') ) {
        my %data = (
            patient_id  => $patient_id,
            practice_id => $practice_id,
        );
        my $rtn = $self->model('Patient')->update_patient_demographics(\%data);
        return $rtn
            ? $self->error($rtn)
            : $self->redirect_after_edit_success('/hmrn_data/=/' . $request_id);
    }
    else { # load existing for editing:
        # get current practice_id for patient:
        my $info = $self->model('HMRN')->get_patient_demographics($patient_id);
    
        return $self->tt_process({ data => $info });
    }
}

# ------------------------------------------------------------------------------
# ajax function called from treatment type select menu:
sub treatment_options : Runmode {
    my $self = shift; $self->_debug_path($self->get_current_runmode);

    my $options = [];
    
    if ( my $tx_type_id = $self->query->param('tx_type_id') ) { # warn $tx_type_id;
    	$options = $self->model('HMRN')->get_tx_details_for_tx_type($tx_type_id);
    }
    
    return $self->tt_process({ options => $options });
}

1;
