<?php

use app\services\CustomerProfileBadges;

defined('BASEPATH') or exit('No direct script access allowed');

/**
 * Check whether the contact email is verified
 *
 * @since  2.2.0
 *
 * @param mixed $id contact id
 *
 * @return bool
 */
function is_contact_email_verified($id = null)
{
    $id = ! $id ? get_contact_user_id() : $id;

    if (isset($GLOBALS['contact']) && $GLOBALS['contact']->id == $id) {
        return ! is_null($GLOBALS['contact']->email_verified_at);
    }

    $CI = &get_instance();

    $CI->db->select('email_verified_at');
    $CI->db->where('id', $id);
    $contact = $CI->db->get(db_prefix() . 'contacts')->row();

    if (! $contact) {
        return false;
    }

    return ! is_null($contact->email_verified_at);
}

/**
 * Check whether the user disabled verification emails for contacts
 *
 * @return bool
 */
function is_email_verification_enabled()
{
    return total_rows(db_prefix() . 'emailtemplates', ['slug' => 'contact-verification-email', 'active' => 0]) == 0;
}
/**
 * Check if client id is used in the system
 *
 * @param mixed $id client id
 *
 * @return bool
 */
function is_client_id_used($id)
{
    $total = 0;

    $checkCommonTables = [db_prefix() . 'subscriptions', db_prefix() . 'creditnotes', db_prefix() . 'projects', db_prefix() . 'invoices', db_prefix() . 'expenses', db_prefix() . 'estimates'];

    foreach ($checkCommonTables as $table) {
        $total += total_rows($table, [
            'client' => $id,
        ]);
    }

    $total += total_rows(db_prefix() . 'contracts', [
        'client' => $id,
    ]);

    $total += total_rows(db_prefix() . 'proposals', [
        'rel_id'   => $id,
        'rel_type' => 'customer',
    ]);

    $total += total_rows(db_prefix() . 'tickets', [
        'userid' => $id,
    ]);

    $total += total_rows(db_prefix() . 'tasks', [
        'rel_id'   => $id,
        'rel_type' => 'customer',
    ]);

    return hooks()->apply_filters('is_client_id_used', $total > 0 ? true : false, $id);
}
/**
 * Check if customer has subscriptions
 *
 * @param mixed $id customer id
 *
 * @return bool
 */
function customer_has_subscriptions($id)
{
    return hooks()->apply_filters('customer_has_subscriptions', total_rows(db_prefix() . 'subscriptions', ['clientid' => $id]) > 0);
}
/**
 * Get client by ID or current queried client
 *
 * @param mixed $id client id
 *
 * @return mixed
 */
function get_client($id = null)
{
    if (empty($id) && isset($GLOBALS['client'])) {
        return $GLOBALS['client'];
    }

    // Client global object not set
    if (empty($id)) {
        return null;
    }

    $client = get_instance()->clients_model->get($id);

    return $client;
}
/**
 * Get predefined tabs array, used in customer profile
 *
 * @return array
 */
function get_customer_profile_tabs()
{
    return get_instance()->app_tabs->get_customer_profile_tabs();
}

/**
 * Filter only visible tabs selected from the profile and add badge
 *
 * @param array $tabs available tabs
 * @param int   $id   client
 *
 * @return array
 */
function filter_client_visible_tabs($tabs, $id = '')
{
    $newTabs               = [];
    $customerProfileBadges = null;

    $visible = get_option('visible_customer_profile_tabs');
    if ($visible != 'all') {
        $visible = unserialize($visible);
    }

    if ($id !== '') {
        $customerProfileBadges = new CustomerProfileBadges($id);
    }

    $appliedSettings = is_array($visible);

    foreach ($tabs as $key => $tab) {
        // Check visibility from settings too
        if ($key != 'profile' && $key != 'contacts' && $appliedSettings) {
            if (array_key_exists($key, $visible) && $visible[$key] == false) {
                continue;
            }
        }

        if (! is_null($customerProfileBadges)) {
            $tab['badge'] = $customerProfileBadges->getBadge($tab['slug']);
        }

        $newTabs[$key] = $tab;
    }

    return hooks()->apply_filters('client_filtered_visible_tabs', $newTabs);
}
/**
 * @todo
 * Find a way to get the customer_id inside this function or refactor the hook
 *
 * @param string $group the tabs groups
 *
 * @return null
 */
function app_init_customer_profile_tabs()
{
    $client_id = null;

    $remindersText = _l('client_reminders_tab');

    if ($client = get_client()) {
        $client_id = $client->userid;

        $total_reminders = total_rows(
            db_prefix() . 'reminders',
            [
                'isnotified' => 0,
                'staff'      => get_staff_user_id(),
                'rel_type'   => 'customer',
                'rel_id'     => $client_id,
            ]
        );

        if ($total_reminders > 0) {
            $remindersText .= ' <span class="badge">' . $total_reminders . '</span>';
        }
    }

    $CI = &get_instance();

    $CI->app_tabs->add_customer_profile_tab('profile', [
        'name'     => _l('client_add_edit_profile'),
        'icon'     => 'fa fa-user-circle',
        'view'     => 'admin/clients/groups/profile',
        'position' => 5,
        'badge'    => [],
    ]);

    $CI->app_tabs->add_customer_profile_tab('contacts', [
        'name'     => ! is_empty_customer_company($client_id) || empty($client_id) ? _l('customer_contacts') : _l('contact'),
        'icon'     => 'fa-regular fa-user',
        'view'     => 'admin/clients/groups/contacts',
        'position' => 10,
        'badge'    => [],
    ]);

    $CI->app_tabs->add_customer_profile_tab('notes', [
        'name'     => _l('contracts_notes_tab'),
        'icon'     => 'fa-regular fa-note-sticky',
        'view'     => 'admin/clients/groups/notes',
        'position' => 15,
        'badge'    => [],
    ]);

    $CI->app_tabs->add_customer_profile_tab('statement', [
        'name'     => _l('customer_statement'),
        'icon'     => 'fa fa-area-chart',
        'view'     => 'admin/clients/groups/statement',
        'visible'  => staff_can('view', 'invoices'),
        'position' => 20,
        'badge'    => [],
    ]);

    $CI->app_tabs->add_customer_profile_tab('invoices', [
        'name'     => _l('client_invoices_tab'),
        'icon'     => 'fa fa-file-text',
        'view'     => 'admin/clients/groups/invoices',
        'visible'  => (staff_can('view', 'invoices') || staff_can('view_own', 'invoices') || (get_option('allow_staff_view_invoices_assigned') == 1 && staff_has_assigned_invoices())),
        'position' => 25,
        'badge'    => [],
    ]);

    $CI->app_tabs->add_customer_profile_tab('payments', [
        'name'     => _l('client_payments_tab'),
        'icon'     => 'fa fa-line-chart',
        'view'     => 'admin/clients/groups/payments',
        'visible'  => (staff_can('view', 'payments') || staff_can('view_own', 'invoices') || (get_option('allow_staff_view_invoices_assigned') == 1 && staff_has_assigned_invoices())),
        'position' => 30,
        'badge'    => [],
    ]);

    $CI->app_tabs->add_customer_profile_tab('proposals', [
        'name'     => _l('proposals'),
        'icon'     => 'fa-regular fa-file-powerpoint',
        'view'     => 'admin/clients/groups/proposals',
        'visible'  => (staff_can('view', 'proposals') || staff_can('view_own', 'proposals') || (get_option('allow_staff_view_proposals_assigned') == 1 && staff_has_assigned_proposals())),
        'position' => 35,
        'badge'    => [],
    ]);

    $CI->app_tabs->add_customer_profile_tab('credit_notes', [
        'name'     => _l('credit_notes'),
        'icon'     => 'fa-regular fa-file-lines',
        'view'     => 'admin/clients/groups/credit_notes',
        'visible'  => (staff_can('view', 'credit_notes') || staff_can('view_own', 'credit_notes')),
        'position' => 40,
        'badge'    => [],
    ]);

    $CI->app_tabs->add_customer_profile_tab('estimates', [
        'name'     => _l('estimates'),
        'icon'     => 'fa-regular fa-file',
        'view'     => 'admin/clients/groups/estimates',
        'visible'  => (staff_can('view', 'estimates') || staff_can('view_own', 'estimates') || (get_option('allow_staff_view_estimates_assigned') == 1 && staff_has_assigned_estimates())),
        'position' => 45,
        'badge'    => [],
    ]);

    $CI->app_tabs->add_customer_profile_tab('subscriptions', [
        'name'     => _l('subscriptions'),
        'icon'     => 'fa fa-repeat',
        'view'     => 'admin/clients/groups/subscriptions',
        'visible'  => (staff_can('view', 'subscriptions') || staff_can('view_own', 'subscriptions')),
        'position' => 50,
        'badge'    => [],
    ]);

    $CI->app_tabs->add_customer_profile_tab('expenses', [
        'name'     => _l('expenses'),
        'icon'     => 'fa-regular fa-file-lines',
        'view'     => 'admin/clients/groups/expenses',
        'visible'  => (staff_can('view', 'expenses') || staff_can('view_own', 'expenses')),
        'position' => 55,
        'badge'    => [],
    ]);

    $CI->app_tabs->add_customer_profile_tab('contracts', [
        'name'     => _l('contracts'),
        'icon'     => 'fa-regular fa-note-sticky',
        'view'     => 'admin/clients/groups/contracts',
        'visible'  => (staff_can('view', 'contracts') || staff_can('view_own', 'contracts')),
        'position' => 60,
        'badge'    => [],
    ]);

    $CI->app_tabs->add_customer_profile_tab('projects', [
        'name'     => _l('projects'),
        'icon'     => 'fa-solid fa-chart-gantt',
        'view'     => 'admin/clients/groups/projects',
        'position' => 65,
        'badge'    => [],
    ]);

    $CI->app_tabs->add_customer_profile_tab('tasks', [
        'name'     => _l('tasks'),
        'icon'     => 'fa-regular fa-circle-check',
        'view'     => 'admin/clients/groups/tasks',
        'position' => 70,
        'badge'    => [],
    ]);

    $CI->app_tabs->add_customer_profile_tab('tickets', [
        'name'     => _l('tickets'),
        'icon'     => 'fa-regular fa-life-ring',
        'view'     => 'admin/clients/groups/tickets',
        'visible'  => ((get_option('access_tickets_to_none_staff_members') == 1 && ! is_staff_member()) || is_staff_member()),
        'position' => 75,
        'badge'    => [],
    ]);

    $CI->app_tabs->add_customer_profile_tab('attachments', [
        'name'     => _l('customer_attachments'),
        'icon'     => 'fa fa-paperclip',
        'view'     => 'admin/clients/groups/attachments',
        'position' => 80,
        'badge'    => [],
    ]);

    $CI->app_tabs->add_customer_profile_tab('vault', [
        'name'     => _l('vault'),
        'icon'     => 'fa fa-lock',
        'view'     => 'admin/clients/groups/vault',
        'position' => 85,
        'badge'    => [],
    ]);

    $CI->app_tabs->add_customer_profile_tab('reminders', [
        'name'     => $remindersText,
        'icon'     => 'fa-regular fa-bell',
        'view'     => 'admin/clients/groups/reminders',
        'position' => 90,
        'badge'    => [],
    ]);

    $CI->app_tabs->add_customer_profile_tab('map', [
        'name'     => _l('customer_map'),
        'icon'     => 'fa-solid fa-location-dot',
        'view'     => 'admin/clients/groups/map',
        'position' => 95,
        'badge'    => [],
    ]);
}

/**
 * Get client id by lead id
 *
 * @since  Version 1.0.1
 *
 * @param mixed $id lead id
 *
 * @return mixed client id
 */
function get_client_id_by_lead_id($id)
{
    $CI = &get_instance();
    $CI->db->select('userid')->from(db_prefix() . 'clients')->where('leadid', $id);

    return $CI->db->get()->row()->userid;
}

/**
 * Check if contact id passed is primary contact
 * If you dont pass $contact_id the current logged in contact will be checked
 *
 * @param string $contact_id
 *
 * @return bool
 */
function is_primary_contact($contact_id = '')
{
    if (! is_numeric($contact_id)) {
        $contact_id = get_contact_user_id();
    }

    return (bool) (total_rows(db_prefix() . 'contacts', ['id' => $contact_id, 'is_primary' => 1]) > 0);
}

/**
 * Check if client have invoices with multiple currencies
 *
 * @param mixed      $clientid
 * @param mixed|null $table
 *
 * @return booelan
 */
function is_client_using_multiple_currencies($clientid = '', $table = null)
{
    if (! $table) {
        $table = db_prefix() . 'invoices';
    }

    $CI = &get_instance();

    $clientid = $clientid == '' ? get_client_user_id() : $clientid;
    $CI->load->model('currencies_model');
    $currencies            = $CI->currencies_model->get();
    $total_currencies_used = 0;

    foreach ($currencies as $currency) {
        $CI->db->where('currency', $currency['id']);
        $CI->db->where('clientid', $clientid);
        $total = $CI->db->count_all_results($table);
        if ($total > 0) {
            $total_currencies_used++;
        }
    }

    $retVal = true;
    if ($total_currencies_used > 1) {
        $retVal = true;
    } elseif ($total_currencies_used == 0 || $total_currencies_used == 1) {
        $retVal = false;
    }

    return hooks()->apply_filters('is_client_using_multiple_currencies', $retVal, [
        'client_id' => $clientid,
        'table'     => $table,
    ]);
}

/**
 * Function used to check if is really empty customer company
 * Can happen user to have selected that the company field is not required and the primary contact name is auto added in the company field
 *
 * @param mixed $id
 *
 * @return bool
 */
function is_empty_customer_company($id)
{
    $CI = &get_instance();
    $CI->db->select('company');
    $CI->db->from(db_prefix() . 'clients');
    $CI->db->where('userid', $id);
    $row = $CI->db->get()->row();
    if ($row) {
        return (bool) ($row->company == '');
    }

    return true;
}

/**
 * Get ids to check what files with contacts are shared
 *
 * @param array $where
 *
 * @return array
 */
function get_customer_profile_file_sharing($where = [])
{
    $CI = &get_instance();
    $CI->db->where($where);

    return $CI->db->get(db_prefix() . 'shared_customer_files')->result_array();
}

/**
 * Get customer id by passed contact id
 *
 * @param mixed $id
 *
 * @return mixed
 */
function get_user_id_by_contact_id($id)
{
    $CI = &get_instance();

    $userid = $CI->app_object_cache->get('user-id-by-contact-id-' . $id);
    if (! $userid) {
        $CI->db->select('userid')
            ->where('id', $id);
        $client = $CI->db->get(db_prefix() . 'contacts')->row();

        if ($client) {
            $userid = $client->userid;
            $CI->app_object_cache->add('user-id-by-contact-id-' . $id, $userid);
        }
    }

    return $userid;
}

/**
 * Get primary contact user id for specific customer
 *
 * @param mixed $userid
 *
 * @return mixed
 */
function get_primary_contact_user_id($userid)
{
    $CI = &get_instance();
    $CI->db->where('userid', $userid);
    $CI->db->where('is_primary', 1);
    $row = $CI->db->get(db_prefix() . 'contacts')->row();

    if ($row) {
        return $row->id;
    }

    return false;
}

/**
 * Get client full name
 *
 * @param string $contact_id Optional
 *
 * @return string Firstname and Lastname
 */
function get_contact_full_name($contact_id = '')
{
    $contact_id == '' ? get_contact_user_id() : $contact_id;

    $CI = &get_instance();

    $contact = $CI->app_object_cache->get('contact-full-name-data-' . $contact_id);

    if (! $contact) {
        $CI->db->where('id', $contact_id);
        $contact = $CI->db->select('firstname,lastname')->from(db_prefix() . 'contacts')->get()->row();
        $CI->app_object_cache->add('contact-full-name-data-' . $contact_id, $contact);
    }

    if ($contact) {
        return $contact->firstname . ' ' . $contact->lastname;
    }

    return '';
}
/**
 * Return contact profile image url
 *
 * @param mixed  $contact_id
 * @param string $type
 *
 * @return string
 */
function contact_profile_image_url($contact_id, $type = 'small')
{
    $url  = base_url('assets/images/user-placeholder.jpg');
    $CI   = &get_instance();
    $path = $CI->app_object_cache->get('contact-profile-image-path-' . $contact_id);

    if (! $path) {
        $CI->app_object_cache->add('contact-profile-image-path-' . $contact_id, $url);

        $CI->db->select('profile_image');
        $CI->db->from(db_prefix() . 'contacts');
        $CI->db->where('id', $contact_id);
        $contact = $CI->db->get()->row();

        if ($contact && ! empty($contact->profile_image)) {
            $path = 'uploads/client_profile_images/' . $contact_id . '/' . $type . '_' . $contact->profile_image;
            $CI->app_object_cache->set('contact-profile-image-path-' . $contact_id, $path);
        }
    }

    if ($path && file_exists($path)) {
        $url = base_url($path);
    }

    return $url;
}
/**
 * Used in:
 * Search contact tickets
 * Project dropdown quick switch
 * Calendar tooltips
 *
 * @param  [type] $userid [description]
 * @param mixed $prevent_empty_company
 *
 * @return [type]         [description]
 */
function get_company_name($userid, $prevent_empty_company = false)
{
    $_userid = get_client_user_id();
    if ($userid !== '') {
        $_userid = $userid;
    }
    $CI = &get_instance();

    $select = ($prevent_empty_company == false ? get_sql_select_client_company() : 'company');

    $client = $CI->db->select($select)
        ->where('userid', $_userid)
        ->from(db_prefix() . 'clients')
        ->get()
        ->row();
    if ($client) {
        return $client->company;
    }

    return '';
}

/**
 * Get client default language
 *
 * @param mixed $clientid
 *
 * @return mixed
 */
function get_client_default_language($clientid = '')
{
    if (! is_numeric($clientid)) {
        $clientid = get_client_user_id();
    }

    $CI = &get_instance();
    $CI->db->select('default_language');
    $CI->db->from(db_prefix() . 'clients');
    $CI->db->where('userid', $clientid);
    $client = $CI->db->get()->row();
    if ($client) {
        return $client->default_language;
    }

    return '';
}

/**
 * Function is customer admin
 *
 * @param mixed    $id       customer id
 * @param staff_id $staff_id staff id to check
 *
 * @return bool
 */
function is_customer_admin($id, $staff_id = '')
{
    $staff_id = is_numeric($staff_id) ? $staff_id : get_staff_user_id();
    $CI       = &get_instance();
    $cache    = $CI->app_object_cache->get($id . '-is-customer-admin-' . $staff_id);

    if ($cache) {
        return $cache['retval'];
    }

    $total = total_rows(db_prefix() . 'customer_admins', [
        'customer_id' => $id,
        'staff_id'    => $staff_id,
    ]);

    $retval = $total > 0 ? true : false;
    $CI->app_object_cache->add($id . '-is-customer-admin-' . $staff_id, ['retval' => $retval]);

    return $retval;
}
/**
 * Check if staff member have assigned customers
 *
 * @param mixed $staff_id staff id
 *
 * @return bool
 */
function have_assigned_customers($staff_id = '')
{
    $CI       = &get_instance();
    $staff_id = is_numeric($staff_id) ? $staff_id : get_staff_user_id();
    $cache    = $CI->app_object_cache->get('staff-total-assigned-customers-' . $staff_id);

    if (is_numeric($cache)) {
        $result = $cache;
    } else {
        $result = total_rows(db_prefix() . 'customer_admins', [
            'staff_id' => $staff_id,
        ]);
        $CI->app_object_cache->add('staff-total-assigned-customers-' . $staff_id, $result);
    }

    return $result > 0 ? true : false;
}
/**
 * Check if contact has permission
 *
 * @param string $permission permission name
 * @param string $contact_id contact id
 *
 * @return bool
 */
function has_contact_permission($permission, $contact_id = '')
{
    $CI = &get_instance();

    if (! class_exists('app')) {
        $CI->load->library('app');
    }

    $permissions = get_contact_permissions();

    if (empty($contact_id)) {
        $contact_id = get_contact_user_id();
    }

    foreach ($permissions as $_permission) {
        if ($_permission['short_name'] == $permission) {
            return total_rows(db_prefix() . 'contact_permissions', [
                'permission_id' => $_permission['id'],
                'userid'        => $contact_id,
            ]) > 0;
        }
    }

    return false;
}
/**
 * Load customers area language
 *
 * @param string $customer_id
 *
 * @return string return loaded language
 */
function load_client_language($customer_id = '')
{
    $CI = &get_instance();
    if (! $CI->load->is_loaded('cookie')) {
        $CI->load->helper('cookie');
    }

    if (defined('CLIENTS_AREA') && get_contact_language() != '' && ! is_language_disabled()) {
        $language = get_contact_language();
    } else {
        $language = get_option('active_language');

        if ((is_client_logged_in() || $customer_id != '') && ! is_language_disabled()) {
            $client_language = get_client_default_language($customer_id);

            if (
                ! empty($client_language)
                && file_exists(APPPATH . 'language/' . $client_language)
            ) {
                $language = $client_language;
            }
        }

        // set_contact_language($language);
    }

    $CI->lang->is_loaded = [];
    $CI->lang->language  = [];

    $CI->lang->load($language . '_lang', $language);
    load_custom_lang_file($language);

    $GLOBALS['language'] = $language;

    $GLOBALS['locale'] = get_locale_key($language);

    $CI->lang->set_last_loaded_language($language);

    hooks()->do_action('after_load_client_language', $language);

    return $language;
}
/**
 * Check if client have transactions recorded
 *
 * @param mixed $id clientid
 *
 * @return bool
 */
function client_have_transactions($id)
{
    $total = 0;

    foreach ([db_prefix() . 'invoices', db_prefix() . 'creditnotes', db_prefix() . 'estimates'] as $table) {
        $total += total_rows($table, [
            'clientid' => $id,
        ]);
    }

    $total += total_rows(db_prefix() . 'expenses', [
        'clientid' => $id,
        'billable' => 1,
    ]);

    $total += total_rows(db_prefix() . 'proposals', [
        'rel_id'   => $id,
        'rel_type' => 'customer',
    ]);

    return hooks()->apply_filters('customer_have_transactions', $total > 0, $id);
}

/**
 * Predefined contact permission
 *
 * @return array
 */
function get_contact_permissions()
{
    $permissions = [
        [
            'id'         => 1,
            'name'       => _l('customer_permission_invoice'),
            'short_name' => 'invoices',
        ],
        [
            'id'         => 2,
            'name'       => _l('customer_permission_estimate'),
            'short_name' => 'estimates',
        ],
        [
            'id'         => 3,
            'name'       => _l('customer_permission_contract'),
            'short_name' => 'contracts',
        ],
        [
            'id'         => 4,
            'name'       => _l('customer_permission_proposal'),
            'short_name' => 'proposals',
        ],
        [
            'id'         => 5,
            'name'       => _l('customer_permission_support'),
            'short_name' => 'support',
        ],
        [
            'id'         => 6,
            'name'       => _l('customer_permission_projects'),
            'short_name' => 'projects',
        ],
    ];

    return hooks()->apply_filters('get_contact_permissions', $permissions);
}

function get_contact_permission($name)
{
    $permissions = get_contact_permissions();

    foreach ($permissions as $permission) {
        if ($permission['short_name'] == $name) {
            return $permission;
        }
    }

    return false;
}

/**
 * Additional checking for customers area, when contact edit his profile
 * This function will check if the checkboxes for email notifications should be shown
 *
 * @return bool
 */
function can_contact_view_email_notifications_options()
{
    return has_contact_permission('invoices')
        || has_contact_permission('estimates')
        || has_contact_permission('projects')
        || has_contact_permission('contracts');
}

/**
 * With this function staff can login as client in the clients area
 *
 * @param mixed $id client id
 */
function login_as_client($id)
{
    $CI = &get_instance();

    $CI->db->select(db_prefix() . 'contacts.id, active')
        ->where('userid', $id)
        ->where('is_primary', 1);

    $primary = $CI->db->get(db_prefix() . 'contacts')->row();

    if (! $primary) {
        set_alert('danger', _l('no_primary_contact'));
        redirect(previous_url() ?: $_SERVER['HTTP_REFERER']);
    } elseif ($primary->active == '0') {
        set_alert('danger', 'Customer primary contact is not active, please set the primary contact as active in order to login as client');
        redirect(previous_url() ?: $_SERVER['HTTP_REFERER']);
    }

    $CI->load->model('announcements_model');
    $CI->announcements_model->set_announcements_as_read_except_last_one($primary->id);

    $user_data = [
        'client_user_id'      => $id,
        'contact_user_id'     => $primary->id,
        'client_logged_in'    => true,
        'logged_in_as_client' => true,
    ];

    $CI->session->set_userdata($user_data);
}

function send_customer_registered_email_to_administrators($client_id)
{
    $CI = &get_instance();
    $CI->load->model('staff_model');
    $admins = $CI->staff_model->get('', ['active' => 1, 'admin' => 1]);

    foreach ($admins as $admin) {
        send_mail_template('customer_new_registration_to_admins', $admin['email'], $client_id, $admin['staffid']);
    }
}

/**
 * Return and perform additional checkings for contact consent url
 *
 * @param mixed $contact_id contact id
 *
 * @return string
 */
function contact_consent_url($contact_id)
{
    $CI = &get_instance();

    $consent_key = get_contact_meta($contact_id, 'consent_key');

    if (empty($consent_key)) {
        $consent_key = app_generate_hash() . '-' . app_generate_hash();
        $meta_id     = false;
        if (total_rows(db_prefix() . 'contacts', ['id' => $contact_id]) > 0) {
            $meta_id = add_contact_meta($contact_id, 'consent_key', $consent_key);
        }
        if (! $meta_id) {
            return '';
        }
    }

    return site_url('consent/contact/' . $consent_key);
}

/**
 *  Get customer attachment
 *
 * @param mixed $id customer id
 *
 * @return array
 */
function get_all_customer_attachments($id)
{
    $CI = &get_instance();

    $attachments = [];

    $attachment_types = [
        'invoice' => [
            'url'                => site_url() . 'download/file/sales_attachment/',
            'upload_path'        => get_upload_path_by_type('invoice'),
            'download_indicator' => 'attachment_key',
            'key_indicator'      => 'rel_id',
        ],
        'estimate' => [
            'url'                => site_url() . 'download/file/sales_attachment/',
            'upload_path'        => get_upload_path_by_type('estimate'),
            'download_indicator' => 'attachment_key',
            'key_indicator'      => 'rel_id',
        ],
        'credit_note' => [
            'url'                => site_url() . 'download/file/sales_attachment/',
            'upload_path'        => get_upload_path_by_type('credit_note'),
            'download_indicator' => 'attachment_key',
            'key_indicator'      => 'rel_id',
        ],
        'proposal' => [
            'url'                => site_url() . 'download/file/sales_attachment/',
            'upload_path'        => get_upload_path_by_type('proposal'),
            'download_indicator' => 'attachment_key',
            'key_indicator'      => 'rel_id',
        ],
        'contract' => [
            'url'                => site_url() . 'download/file/contract/',
            'upload_path'        => get_upload_path_by_type('contract'),
            'download_indicator' => 'attachment_key',
            'key_indicator'      => 'rel_id',
        ],
        'lead' => [
            'url'                => site_url() . 'download/file/lead_attachment/',
            'upload_path'        => get_upload_path_by_type('lead'),
            'download_indicator' => 'id',
            'key_indicator'      => 'rel_id',
        ],
        'task' => [
            'url'                => site_url() . 'download/file/taskattachment/',
            'upload_path'        => get_upload_path_by_type('task'),
            'download_indicator' => 'attachment_key',
            'key_indicator'      => 'rel_id',
        ],
        'customer' => [
            'url'                => site_url() . 'download/file/client/',
            'upload_path'        => get_upload_path_by_type('customer'),
            'download_indicator' => 'attachment_key',
            'key_indicator'      => 'rel_id',
        ],
        'ticket' => [
            'url'                => site_url() . 'download/file/ticket/',
            'upload_path'        => get_upload_path_by_type('ticket'),
            'download_indicator' => 'id',
            'key_indicator'      => 'ticketid',
        ],
        'expense' => [
            'url'                => site_url() . 'download/file/expense/',
            'upload_path'        => get_upload_path_by_type('expense'),
            'download_indicator' => 'rel_id',
            'key_indicator'      => 'rel_id',
        ],
    ];

    foreach ($attachment_types as $type => $settings) {
        $attachments[$type] = []; // create empty array for each type
    }

    $can_view_expenses     = staff_can('view', 'expenses');
    $can_view_own_expenses = staff_can('view_own', 'expenses');
    if ($can_view_expenses || $can_view_own_expenses) {
        $CI->db->select('clientid,id')->where('clientid', $id);
        if (! $can_view_expenses) {
            $CI->db->where('addedfrom', get_staff_user_id());
        }
        $CI->db->from(db_prefix() . 'expenses');
        $expenses = $CI->db->get()->result_array();
        $ids      = array_column($expenses, 'id');
        if (count($ids) > 0) {
            $CI->db->where_in('rel_id', $ids)->where('rel_type', 'expense');
            $_attachments = $CI->db->get(db_prefix() . 'files')->result_array();

            foreach ($_attachments as $_att) {
                $_att['download_url'] = $attachment_types['expense']['url'] . $_att[$attachment_types['expense']['download_indicator']];
                $_att['upload_path']  = $attachment_types['expense']['upload_path'] . $_att[$attachment_types['expense']['key_indicator']] . '/' . $_att['file_name'];
                array_push($attachments['expense'], $_att);
            }
        }
    }

    if (staff_can('view', 'invoices') || staff_can('view_own', 'invoices') || get_option('allow_staff_view_invoices_assigned') == 1) {
        $noPermissionQuery = get_invoices_where_sql_for_staff(get_staff_user_id());
        $CI->db->select('clientid,id')->where('clientid', $id);

        if (! staff_can('view', 'invoices')) {
            $CI->db->where($noPermissionQuery);
        }

        $CI->db->from(db_prefix() . 'invoices');
        $invoices = $CI->db->get()->result_array();
        $ids      = array_column($invoices, 'id');

        if (! empty($ids)) {
            $CI->db->where_in('rel_id', $ids)->where('rel_type', 'invoice');
            $_attachments = $CI->db->get(db_prefix() . 'files')->result_array();

            foreach ($_attachments as $_att) {
                $_att['download_url'] = $attachment_types['invoice']['url'] . $_att[$attachment_types['invoice']['download_indicator']];
                $_att['upload_path']  = $attachment_types['invoice']['upload_path'] . $_att[$attachment_types['invoice']['key_indicator']] . '/' . $_att['file_name'];
                array_push($attachments['invoice'], $_att);
            }
        }
    }
    if (staff_can('view', 'credit_notes') || staff_can('view_own', 'credit_notes')) {
        $CI->db->select('clientid,id')->where('clientid', $id);

        if (! staff_can('view', 'credit_notes')) {
            $CI->db->where('addedfrom', get_staff_user_id());
        }

        $CI->db->from(db_prefix() . 'creditnotes');
        $credit_notes = $CI->db->get()->result_array();
        $ids          = array_column($credit_notes, 'id');

        if (! empty($ids)) {
            $CI->db->where_in('rel_id', $ids)->where('rel_type', 'credit_note');
            $_attachments = $CI->db->get(db_prefix() . 'files')->result_array();

            foreach ($_attachments as $_att) {
                $_att['download_url'] = $attachment_types['credit_note']['url'] . $_att[$attachment_types['credit_note']['download_indicator']];
                $_att['upload_path']  = $attachment_types['credit_note']['upload_path'] . $_att[$attachment_types['credit_note']['key_indicator']] . '/' . $_att['file_name'];
                array_push($attachments['credit_note'], $_att);
            }
        }
    }

    if (staff_can('view', 'estimates') || staff_can('view_own', 'estimates') || get_option('allow_staff_view_proposals_assigned') == 1) {
        $noPermissionQuery = get_estimates_where_sql_for_staff(get_staff_user_id());
        $CI->db->select('clientid,id')->where('clientid', $id);

        if (! staff_can('view', 'estimates')) {
            $CI->db->where($noPermissionQuery);
        }

        $CI->db->from(db_prefix() . 'estimates');
        $estimates = $CI->db->get()->result_array();
        $ids       = array_column($estimates, 'id');

        if (! empty($ids)) {
            $CI->db->where_in('rel_id', $ids)->where('rel_type', 'estimate');
            $_attachments = $CI->db->get(db_prefix() . 'files')->result_array();

            foreach ($_attachments as $_att) {
                $_att['download_url'] = $attachment_types['estimate']['url'] . $_att[$attachment_types['estimate']['download_indicator']];
                $_att['upload_path']  = $attachment_types['estimate']['upload_path'] . $_att[$attachment_types['estimate']['key_indicator']] . '/' . $_att['file_name'];
                array_push($attachments['estimate'], $_att);
            }
        }
    }

    if (staff_can('view', 'proposals') || staff_can('view_own', 'proposals') || get_option('allow_staff_view_proposals_assigned') == 1) {
        $noPermissionQuery = get_proposals_sql_where_staff(get_staff_user_id());
        $CI->db->select('rel_id,id')->where('rel_id', $id)->where('rel_type', 'customer');

        if (! staff_can('view', 'proposals')) {
            $CI->db->where($noPermissionQuery);
        }

        $CI->db->from(db_prefix() . 'proposals');
        $proposals = $CI->db->get()->result_array();
        $ids       = array_column($proposals, 'id');

        if (! empty($ids)) {
            $CI->db->where_in('rel_id', $ids)->where('rel_type', 'proposal');
            $_attachments = $CI->db->get(db_prefix() . 'files')->result_array();

            foreach ($_attachments as $_att) {
                $_att['download_url'] = $attachment_types['proposal']['url'] . $_att[$attachment_types['proposal']['download_indicator']];
                $_att['upload_path']  = $attachment_types['proposal']['upload_path'] . $_att[$attachment_types['proposal']['key_indicator']] . '/' . $_att['file_name'];
                array_push($attachments['proposal'], $_att);
            }
        }
    }

    $can_view_contracts = staff_can('view', 'contracts');
    if ($can_view_contracts || staff_can('view_own', 'contracts')) {
        $CI->db->select('client,id')->where('client', $id);

        if (! $can_view_contracts) {
            $CI->db->where('addedfrom', get_staff_user_id());
        }

        $CI->db->from(db_prefix() . 'contracts');
        $contracts = $CI->db->get()->result_array();
        $ids       = array_column($contracts, 'id');

        if (! empty($ids)) {
            $CI->db->where_in('rel_id', $ids)->where('rel_type', 'contract');
            $_attachments = $CI->db->get(db_prefix() . 'files')->result_array();

            foreach ($_attachments as $_att) {
                $_att['download_url'] = $attachment_types['contract']['url'] . $_att[$attachment_types['contract']['download_indicator']];
                $_att['upload_path']  = $attachment_types['contract']['upload_path'] . $_att[$attachment_types['contract']['key_indicator']] . '/' . $_att['file_name'];
                array_push($attachments['contract'], $_att);
            }
        }
    }

    $CI->db->select('leadid')->where('userid', $id);
    $customer = $CI->db->get(db_prefix() . 'clients')->row();

    if (! empty($customer->leadid)) {
        $CI->db->where('rel_id', $customer->leadid)->where('rel_type', 'lead');
        $_attachments = $CI->db->get(db_prefix() . 'files')->result_array();

        foreach ($_attachments as $_att) {
            $_att['download_url'] = $attachment_types['lead']['url'] . $_att[$attachment_types['lead']['download_indicator']];
            $_att['upload_path']  = $attachment_types['lead']['upload_path'] . $_att[$attachment_types['lead']['key_indicator']] . '/' . $_att['file_name'];
            array_push($attachments['lead'], $_att);
        }
    }

    $CI->db->select('ticketid,userid')->where('userid', $id);
    $tickets = $CI->db->get(db_prefix() . 'tickets')->result_array();

    $ids = array_column($tickets, 'ticketid');

    if (! empty($ids)) {
        $CI->db->where_in('ticketid', $ids);
        $_attachments = $CI->db->get(db_prefix() . 'ticket_attachments')->result_array();

        foreach ($_attachments as $_att) {
            $_att['download_url'] = $attachment_types['ticket']['url'] . $_att[$attachment_types['ticket']['download_indicator']];
            $_att['upload_path']  = $attachment_types['ticket']['upload_path'] . $_att[$attachment_types['ticket']['key_indicator']] . '/' . $_att['file_name'];
            array_push($attachments['ticket'], $_att);
        }
    }

    if (staff_can('view', 'tasks')) {
        $noPermissionQuery = get_tasks_where_string(false);
        $CI->db->select('rel_id, id')->where('rel_id', $id)->where('rel_type', 'customer');

        if (! staff_can('view', 'tasks')) {
            $CI->db->where($noPermissionQuery);
        }

        $tasks = $CI->db->get(db_prefix() . 'tasks')->result_array();
        $ids   = array_column($tasks, 'id'); // Corrected to fetch 'id' (was 'ticketid')

        if (! empty($ids)) {
            $CI->db->where_in('rel_id', $ids)->where('rel_type', 'task');
            $_attachments = $CI->db->get(db_prefix() . 'files')->result_array();

            foreach ($_attachments as $_att) {
                $_att['download_url'] = $attachment_types['task']['url'] . $_att[$attachment_types['task']['download_indicator']];
                $_att['upload_path']  = $attachment_types['task']['upload_path'] . $_att[$attachment_types['task']['key_indicator']] . '/' . $_att['file_name'];
                array_push($attachments['task'], $_att);
            }
        }
    }

    $CI->db->where('rel_id', $id)->where('rel_type', 'customer');
    $client_main_attachments = $CI->db->get(db_prefix() . 'files')->result_array();

    foreach ($client_main_attachments as &$attachment) {
        $attachment['total_shares'] = total_rows(db_prefix() . 'shared_customer_files', ['file_id' => $attachment['id']]);
        $attachment['shared_with']  = $attachment['total_shares'] > 0 ?
            get_customer_profile_file_sharing(['file_id' => $attachment['id']]) :
            [];

        $attachment['download_url'] = $attachment_types['customer']['url'] . $attachment[$attachment_types['customer']['download_indicator']];
        $attachment['upload_path']  = $attachment_types['customer']['upload_path'] . $attachment[$attachment_types['customer']['key_indicator']] . '/' . $attachment['file_name'];
    }

    $attachments['customer'] = $client_main_attachments;

    return hooks()->apply_filters('all_client_attachments', $attachments, $id);
}

/**
 * Used in customer profile vaults feature to determine if the vault should be shown for staff
 *
 * @param array $entries vault entries from database
 *
 * @return array
 */
function _check_vault_entries_visibility($entries)
{
    $new = [];

    foreach ($entries as $entry) {
        if ($entry['visibility'] != 1) {
            if ($entry['visibility'] == 2 && ! is_admin() && $entry['creator'] != get_staff_user_id()) {
                continue;
            }
            if ($entry['visibility'] == 3 && $entry['creator'] != get_staff_user_id() && ! is_admin()) {
                continue;
            }
        }
        $new[] = $entry;
    }

    if (count($new) == 0) {
        $new = -1;
    }

    return $new;
}
/**
 * Default SQL select for selecting the company
 *
 * @param string $as
 *
 * @return string
 */
function get_sql_select_client_company($as = 'company')
{
    return 'CASE ' . db_prefix() . 'clients.company WHEN \' \' THEN (SELECT CONCAT(firstname, \' \', lastname) FROM ' . db_prefix() . 'contacts WHERE userid = ' . db_prefix() . 'clients.userid and is_primary = 1) ELSE ' . db_prefix() . 'clients.company END as ' . $as;
}

/**
 * @since  2.7.0
 * check if logged in user can manage contacts
 *
 * @return bool
 */
function can_loggged_in_user_manage_contacts()
{
    $id      = get_contact_user_id();
    $contact = get_instance()->clients_model->get_contact($id);

    if (($contact->is_primary != 1) || (get_option('allow_primary_contact_to_manage_other_contacts') != 1)) {
        return false;
    }

    return ! (is_individual_client());
}

/**
 * @since  2.7.0
 * check if logged in customer is an individual
 *
 * @return bool
 */
function is_individual_client()
{
    return is_empty_customer_company(get_client_user_id())
        && total_rows(db_prefix() . 'contacts', ['userid' => get_client_user_id()]) == 1;
}

/**
 * @since  2.7.0
 * Set logged in contact language
 *
 * @param mixed $lang
 * @param mixed $duration
 *
 * @return void
 */
function set_contact_language($lang, $duration = 60 * 60 * 24 * 31 * 3)
{
    set_cookie('contact_language', $lang, $duration);
}

/**
 * @since  2.7.0
 *
 * get logged in contact language
 *
 * @return string
 */
function get_contact_language()
{
    if (! is_null(get_cookie('contact_language'))) {
        $language = get_cookie('contact_language');

        $availableLanguages = get_instance()->app->get_available_languages();

        if (in_array($language, $availableLanguages)) {
            return $language;
        }
    }

    return '';
}

/**
 * @since  2.9.0
 *
 * Indicates whether the contact automatically
 * appended calling codes feature is enabled based on the
 * customer selected country
 *
 * @return bool
 */
function is_automatic_calling_codes_enabled()
{
    return hooks()->apply_filters('automatic_calling_codes_enabled', true);
}

/**
 * @since 3.1.2
 *
 * Get the required fields for registration.
 *
 * @return array
 */
function get_required_fields_for_registration()
{
    $option = get_option('required_register_fields');

    $required = $option ? json_decode($option) : [];

    return [
        'contact' => [
            'contact_firstname'           => ['label' => _l('clients_firstname'), 'is_required' => true, 'disabled' => true],
            'contact_lastname'            => ['label' => _l('clients_lastname'), 'is_required' => true, 'disabled' => true],
            'contact_email'               => ['label' => _l('clients_email'), 'is_required' => true, 'disabled' => true],
            'contact_contact_phonenumber' => ['label' => _l('clients_phone'), 'is_required' => in_array('contact_contact_phonenumber', $required), 'disabled' => false],
            'contact_website'             => ['label' => _l('client_website'), 'is_required' => in_array('contact_website', $required), 'disabled' => false],
            'contact_title'               => ['label' => _l('contact_position'), 'is_required' => in_array('contact_title', $required), 'disabled' => false],
        ],
        'company' => [
            'company_company'     => ['label' => _l('clients_company'), 'is_required' => (bool) get_option('company_is_required'), 'disabled' => true],
            'company_vat'         => ['label' => _l('clients_vat'), 'is_required' => in_array('company_vat', $required), 'disabled' => false],
            'company_phonenumber' => ['label' => _l('clients_phone'), 'is_required' => in_array('company_phonenumber', $required), 'disabled' => false],
            'company_country'     => ['label' => _l('clients_country'), 'is_required' => in_array('company_country', $required), 'disabled' => false],
            'company_city'        => ['label' => _l('clients_city'), 'is_required' => in_array('company_city', $required), 'disabled' => false],
            'company_address'     => ['label' => _l('clients_address'), 'is_required' => in_array('company_address', $required), 'disabled' => false],
            'company_zip'         => ['label' => _l('clients_zip'), 'is_required' => in_array('company_zip', $required), 'disabled' => false],
            'company_state'       => ['label' => _l('clients_state'), 'is_required' => in_array('company_state', $required), 'disabled' => false],
        ],
    ];
}
