package LIMS::Model::PatientCase;

use base 'LIMS::Model::Base';

use strict;
use warnings;

use Data::Dumper;
use Rose::DB::Object::Util qw(:columns);

#-------------------------------------------------------------------------------
# gets patient_case by case_id:
sub get_patient_case {
	my $self    = shift;
	my $case_id = shift;

	my @objects = qw(patient referral_source);

	my $case = LIMS::DB::PatientCase
		->new(id => $case_id)
		->load(with => \@objects, speculative => 1);

	return $case;
}

#-------------------------------------------------------------------------------
# gets patient_cases by patient_id:
sub get_patient_cases {
	my $self = shift;
	my $case_id = shift;

	my %args = (
		require_objects => [ qw(referral_source patient) ],
		query => [ id => $case_id, ]
	);
#$self->set_rose_debug(1);
	my $patient_cases = LIMS::DB::PatientCase::Manager->get_patient_cases(%args);
#$self->set_rose_debug(0);
	return $patient_cases;
}

#-------------------------------------------------------------------------------
sub get_patient_case_by_request_id {
	my ($self, $request_id) = @_;

	my $request_patient_case = LIMS::DB::Request->new(id => $request_id)
		->load(with => 'patient_case');

	return $request_patient_case;
}

#-------------------------------------------------------------------------------
# gets patient_cases by patient_id:
sub get_cases_by_patient_id {
	my $self = shift;
	my $patient_id = shift;

	my %args = (
		require_objects => [ qw(referral_source patient) ],
		query => [ patient_id => $patient_id, ]
	);
#$self->set_rose_debug(1);
	my $patient_cases = LIMS::DB::PatientCase::Manager->get_patient_cases(%args);
#$self->set_rose_debug(0);
	return $patient_cases;
}

#-------------------------------------------------------------------------------
# add new location/unit_number combination:
sub new_patient_case {
	my $self = shift;
	my $data = shift;

	# first check to see if combination already exists:
	my $patient_case = LIMS::DB::PatientCase->new(%$data)->load(speculative => 1);

	if (! $patient_case) {
		$patient_case = LIMS::DB::PatientCase->new(%$data)->save;
	}

	return $patient_case;
}

#-------------------------------------------------------------------------------
sub update_patient_case {
	my $self = shift;
	my $args = shift; # DEBUG $data;

    my $data = $args->{data};
	my $case = LIMS::DB::PatientCase->new(id => $args->{case_id})->load;
    # warn Dumper $case->as_tree;
	$case->unit_number($data->{unit_number});
	$case->referral_source_id($data->{referral_source_id}); #warn Dumper $case->as_tree;

	eval {
		$case->save( changes_only => 1 );
	};

	return $@ if $@;
}

#-------------------------------------------------------------------------------
sub retrieve_patient_data {
    my ($self, $case_id) = @_; # DEBUG $case_id;

# TODO: ignores 'nested_joins => 0'
	my @objects = qw(patient referral_source.referral_type);
#$Rose::DB::Object::Debug=$Rose::DB::Object::Manager::Debug=1;
    my $patient = LIMS::DB::PatientCase
		->new(id => $case_id)
		->load( with => \@objects, nested_joins => 0 );
#$Rose::DB::Object::Debug=$Rose::DB::Object::Manager::Debug=0;
    return $patient;
}

#-------------------------------------------------------------------------------
sub delete_patient_case {
    my $self    = shift;
    my $case_id = shift;

	# return true if the row was deleted or did not exist, false otherwise
	my $result =
		LIMS::DB::PatientCase->new(id => $case_id)->delete;

    return $result; # will return true if success
}

#-------------------------------------------------------------------------------
sub registration_search {
    my $self = shift;
    my $args = shift; # warn Dumper $args;

	my @sort = qw( patient.last_name patient.first_name patient.dob
		request.id patient_case.id ); # last 2 required to force lowest precedence
	my %h = (
		require_objects => [ qw(patient referral_source) ],
		with_objects 	=> 'request',
		sort_by		    => \@sort,
	);
	# ensure no keys of same name passed in, then merge $args with %h:
	map { die 'duplicate key' if $h{$_}; $h{$_} = $args->{$_} } keys %$args;

    my $cases = LIMS::DB::PatientCase::Manager->get_patient_cases(%h);
    return $cases;
}

=begin #------------------------------------------------------------------------
# reverted to Patient::patient_matches_count() again
sub find_patients_count { # TODO: not reliable - see sql output
# may have to use Rose::DB::Object::QueryBuilder, or accept approx value of count
    my $self = shift;
    my $args = shift; # DEBUG $args;

    $args->{require_objects} = 'patient';
	# $args->{group_by} = [ # returns a list instead of single str
	#	qw(last_name first_name dob nhs_number unit_number referral_source_id)
	# ];

    my $rows = LIMS::DB::PatientCase::Manager->get_patient_cases_count(%$args);

    return $rows;
}
=cut

#-------------------------------------------------------------------------------
# called by Patient::add_new() & Ajax::_validate_param() methods:
sub validate_patient_case {
    my $self = shift;
    my $data = shift;

#	my $unit_number_default =
#		LIMS::DB::PatientCase->new->meta->column('unit_number')->default;

	# Rose converts undef vals to 'IS NULL' so would get many matches, so make
	# all $data vals defined so sql reads: foo = '', not: foo IS NULL; need to
	# take local copy of $data so we don't affect original:
	my %cloned_data = map {
		$_ => $data->{$_} || '';
	} keys %$data;

	my %args = (
		with_objects => [ qw(patient referral_source) ],
		query => [
			or => [
				last_name   => { ne => $cloned_data{last_name} },
				first_name  => { ne => $cloned_data{first_name} },
			],
			or => [
				nhs_number  => $cloned_data{nhs_number},
				unit_number => $cloned_data{unit_number},
			],
		],
		group_by => 't2.id', # patients = t2
		sort_by  => [ 't2.last_name', 't2.first_name' ],
	);

	my $patient = LIMS::DB::PatientCase::Manager->get_patient_cases(%args);

	return $patient;
}

1;
