package FixMyStreet::DB::ResultSet::User;
use base 'FixMyStreet::DB::ResultSet';

use strict;
use warnings;

use Moo;
with 'FixMyStreet::Roles::DB::FullTextSearch';
__PACKAGE__->load_components('Helper::ResultSet::Me');
sub text_search_columns { qw(id name email phone) }
sub text_search_nulls { qw(name email phone) }
sub text_search_translate { '@.' }

# The database has a partial unique index on email (when email_verified is
# true), and phone (when phone_verified is true). In the code, we can only
# say these are fully unique indices, which they aren't, as there could be
# multiple identical unverified phone numbers.
#
# We assume that any and all calls to find (also called using find_or_new,
# find_or_create, or update_or_new/create) are to look up verified entries
# only (it would make no sense to find() a non-unique entry). Therefore we
# help the code along by specifying the most appropriate key to use, given
# the data provided, and setting the appropriate verified boolean.

around find => sub {
    my ($orig, $self) = (shift, shift);
    # If there's already a key, assume caller knows what they're doing
    if (ref $_[0] eq 'HASH' && !$_[1]->{key}) {
        if ($_[0]->{id}) {
            $_[1]->{key} = 'primary';
        } elsif (exists $_[0]->{email} && exists $_[0]->{phone}) {
            # If there's both email and phone, caller must also have specified
            # a verified boolean so that we know what we're looking for
            if (!$_[0]->{email_verified} && !$_[0]->{phone_verified}) {
                die "Cannot perform a User find() with both email and phone and no verified";
            }
        } elsif (exists $_[0]->{email}) {
            $_[0]->{email_verified} = 1;
            $_[1]->{key} = 'users_email_verified_key';
        } elsif (exists $_[0]->{phone}) {
            $_[0]->{phone_verified} = 1;
            $_[1]->{key} = 'users_phone_verified_key';
        }
    }
    $self->$orig(@_);
};

1;
