Server : LiteSpeed
System : Linux premium92.web-hosting.com 4.18.0-553.44.1.lve.el8.x86_64 #1 SMP Thu Mar 13 14:29:12 UTC 2025 x86_64
User : rbnsfqys ( 805)
PHP Version : 8.1.33
Disable Function : NONE
Directory :  /home/rbnsfqys/ali.rbn.services/wp-content/plugins/Repairplugin-pro/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]


Current File : /home/rbnsfqys/ali.rbn.services/wp-content/plugins/Repairplugin-pro/enhanced_locations.php
<?php

use RepairPluginPro\RP_Maps_API;

// Exit if accessed directly

defined( 'ABSPATH' ) || exit;

if(!defined('RP_EL_PLUGIN_FILE')) {

    define( 'RP_EL_PLUGIN_FILE', __FILE__ );

    define( 'RP_EL_PLUGIN_BASENAME', plugin_basename( __FILE__ ) );

    define( 'RP_EL_PLUGIN_PATH', plugin_dir_path( __FILE__ ) );

    define( 'RP_EL_PLUGIN_URL', plugin_dir_url( __FILE__ ) );

    if( defined('WP_REPAIR_ASSETS_CACHE_V') ) {

        define( 'RP_EL_ASSETS_CACHE_V', WP_REPAIR_ASSETS_CACHE_V );

        define( 'RP_EL_BASE_SERVER_URL', WP_REPAIR_BASE_SERVER_URL );

    } else {

        define( 'RP_EL_ASSETS_CACHE_V', 'v' . time() );

        define( 'RP_EL_BASE_SERVER_URL', 'https://base.repairplugin.com/' );

    }

    define( 'RP_EL_REPEAT_CRON_AFTER_X_SECONDS', ( 15 * 60 ) ); // 15 minutes

}

function rp_is_active_enhanced_locations_addon() {

    $final_result = RP_EnhancedLocationsAddon::is_active();

    return apply_filters('rp_filter_is_active_enhanced_locations_addon', $final_result);

}

function rp_enhanced_locations_require_message() {
    // Enhanced Locations addon require Repairplugin to be installed and activated
    $mesesage = 'Enhanced Locations addon require Repairplugin to be installed and activated';
    echo '<div class="notice notice-error is-dismissible"><p>' . $mesesage . '</p></div>';

    return;
}

function rp_enhanced_locations_addon_init() {

    if( !defined('WP_REPAIR_PLUGIN_FILE') ) {
        // Add admin notice
        rp_add_action('admin_notices', 'rp_enhanced_locations_require_message');
        return;
    }

    do_action('rp_enhanced_locations_initialize');

}

rp_add_action('init', 'rp_enhanced_locations_addon_init', 1000);

function rp_add_enhanced_locations_tab_in_sidebar( $sidebar_items = array() ) {

    $sidebar_items['enhanced_locations'] = array(
        'title' => 'Enhanced Locations',
        'icon' => 'fas fa-map-marker-alt',
        'link' => createTheLink('enhanced_locations'),
        'render_condition' => true,
        'position' => 15
    );

    return $sidebar_items;

}

add_filter('rp_admin_settings_sidebar_items', 'rp_add_enhanced_locations_tab_in_sidebar');

function rp_enhanced_locations_tab_actual_html() {
    
    $fileName = RP_EL_PLUGIN_PATH . 'html/enhanced_locations_settings_tab.php';

    $fileName = str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $fileName);

    require_once $fileName;

}

function rp_handle_enhanced_locations_page_html( $return = FALSE, $section = '' ) {

    if( $section == 'enhanced_locations' ) {
        // return the html for the dynamic pricing page
        rp_enhanced_locations_tab_actual_html();

        return TRUE;

    }

    return $return;

}

add_filter('rp_returning_admin_setting_page_html', 'rp_handle_enhanced_locations_page_html', 10, 2);


function rp_get_total_schedule_groups() {

    global $rpQuery;

    $table_rs_schedule_groups = $rpQuery->prefix . "rs_schedule_groups";

    $sql = "SELECT COUNT(*) FROM $table_rs_schedule_groups";

    $results = $rpQuery->get_var($sql);

    if( !empty($results) ) {

        return $results;

    }

    return 0;

}

function rp_get_all_schedule_groups( $current_page = 0, $limit = 0 ) {

    global $rpQuery;

    $table_rs_schedule_groups = $rpQuery->prefix . "rs_schedule_groups";

    $offset = 0;

    if( $current_page > 0 ) {

        $offset = ( $current_page - 1 ) * $limit;

    }

    $sql = "SELECT * FROM $table_rs_schedule_groups";

    // Add limit and offset
    if( $limit > 0 ) {

        $sql .= " LIMIT $limit";

    }

    if( $offset > 0 ) {

        $sql .= " OFFSET $offset";

    }

    $results = $rpQuery->get_results($sql);

    if( !empty($results) ) {

        return $results;

    }

    return array();

}

function rp_get_schedule_group_timing( $schedule_group_id = 0 ) {

    global $rpQuery;

    $schedule_group_id = (int) $schedule_group_id;

    $table_rs_schedule_group_timing = $rpQuery->prefix . "rs_schedule_group_timing";

    $sql = "SELECT * FROM $table_rs_schedule_group_timing WHERE `schedule_group_id` = $schedule_group_id";

    $results = $rpQuery->get_results($sql);

    if( !empty($results) ) {

        return $results;

    }

    return array();

}

function rp_verify_enhanced_location_is_active() {

    if( rp_is_active_enhanced_locations_addon() === false ) {

        echo json_encode(Array('status'=> false, 'rp_validation_error'  => 'Something went wrong. Please try again later.'));

        exit;

    }

}

function rp_delete_schedule_group(){

    rp_verify_enhanced_location_is_active();

    rp_verify_csrf_token_for_ajax('enhanced_locations');

    rp_verify_user_full_access_ajax();

    global $rpQuery;

    $id = (int) ($_POST['id'] ?? 0);

    if( $id <= 0 ) {

        echo json_encode(Array('status'=> false, 'rp_validation_error'  => 'Invalid ID'));

        exit;

    }

    $table_rs_schedule_groups = $rpQuery->prefix . "rs_schedule_groups";

    $table_rs_schedule_group_timing = $rpQuery->prefix . "rs_schedule_group_timing";

    // make sure it is not the last schedule group
    $total_schedule_groups = rp_get_total_schedule_groups();

    if( $total_schedule_groups <= 1 ) {

        echo json_encode(Array('status'=> false, 'rp_validation_error'  => 'You cannot delete the last schedule group'));

        exit;

    }

    // check if this schedule group is assigned to any location
    $rs_company_location = $rpQuery->prefix . "rs_company_location";

    $sql = "SELECT COUNT(*) FROM $rs_company_location WHERE `schedule_group_id` = $id";

    $results = $rpQuery->get_var($sql);
    
    $in_use = FALSE; 

    if( !empty($results) ) {

        $in_use = TRUE;

    }

    // if in_use, make sure we receive alt_schedule_group_id in $_POST and that id is not equal to current schedule group id and that id should be a valid schedule group id
    if( $in_use === TRUE ) {

        $alt_schedule_group_id = (int) ($_POST['alt_schedule_group_id'] ?? 0);

        if( $alt_schedule_group_id <= 0 ) {

            echo json_encode(Array('status'=> false, 'rp_validation_error'  => 'Invalid Alternative Schedule Group ID'));

            exit;

        }

        if( $alt_schedule_group_id == $id ) {

            echo json_encode(Array('status'=> false, 'rp_validation_error'  => 'Alternative Schedule Group ID cannot be same as current Schedule Group ID'));

            exit;

        }

        $sql = "SELECT COUNT(*) FROM $table_rs_schedule_groups WHERE `id` = $alt_schedule_group_id";

        $results = $rpQuery->get_var($sql);

        if( empty($results) ) {

            echo json_encode(Array('status'=> false, 'rp_validation_error'  => 'Invalid Alternative Schedule Group ID'));

            exit;

        }

        // update all locations with alt_schedule_group_id
        $sql = "UPDATE `$rs_company_location` SET `schedule_group_id` = $alt_schedule_group_id WHERE `schedule_group_id` = $id";

        $rpQuery->query($sql);

    }

    $sql = "DELETE FROM `$table_rs_schedule_groups` WHERE `id` = $id";

    $rpQuery->query($sql);

    $sql = "DELETE FROM `$table_rs_schedule_group_timing` WHERE `schedule_group_id` = $id";

    $rpQuery->query($sql);

    echo json_encode(Array('status'=> true, 'message'  => 'Successfully deleted'));

    exit;

}

function rp_deleting_schedule_group(){

    rp_verify_enhanced_location_is_active();

    rp_verify_csrf_token_for_ajax('enhanced_locations');

    rp_verify_user_full_access_ajax();

    global $rpQuery;

    $id = (int) ($_POST['id'] ?? 0);

    if( $id <= 0 ) {

        echo json_encode(Array('status'=> false, 'rp_validation_error'  => 'Invalid ID'));

        exit;

    }

    $available_schedules = rp_get_all_schedule_groups();
    
    // loop through all available schedules and remove the $id from the array
    foreach( $available_schedules as $key => $schedule ) {

        if( $schedule->id == $id ) {

            unset($available_schedules[$key]);

        }

    }

    $available_schedules = array_values($available_schedules);

    // check if any rs_company_location is using this schedule group
    $table_rs_company_location = $rpQuery->prefix . "rs_company_location";

    $sql = "SELECT * FROM `$table_rs_company_location` WHERE `schedule_group_id` = $id";

    $results = $rpQuery->get_results($sql);

    $in_use = 0;

    if( !empty($results) ) {

        $in_use = 1;

    }

    echo json_encode(Array('status'=> true, 'available_schedules'  => $available_schedules, 'in_use' => $in_use));

    exit;

}

function rp_deleting_location(){

    rp_verify_enhanced_location_is_active();

    rp_verify_csrf_token_for_ajax('enhanced_locations');

    rp_verify_user_full_access_ajax();

    global $rpQuery;

    $id = (int) ($_POST['id'] ?? 0);

    if( $id <= 0 ) {

        echo json_encode(Array('status'=> false, 'rp_validation_error'  => 'Invalid ID'));

        exit;

    }

    // check if any rs_company_location is using this schedule group
    $table_rs_company_location = $rpQuery->prefix . "rs_company_location";

    // make sure it is not the last location
    $total_locations = $rpQuery->get_var("SELECT COUNT(*) FROM $table_rs_company_location");

    $safe_to_delete = false;

    if( $total_locations > 1 ) {

        $safe_to_delete = true;

    }

    echo json_encode(Array('status'=> true, 'safe_to_delete' => $safe_to_delete));

    exit;

}

function rp_el_apply_limit_to_locations( $locations = array() ) {

    if( empty( $locations ) ) {

        return $locations;

    }

    if( !RP_EnhancedLocationsAddon::is_active() ) {

        // Enhanced Locations isn't active
        // So no need to apply limit
        return $locations;

    }

    $the_limit = RP_EnhancedLocationsAddon::get_limit();

    if( $the_limit === FALSE ) {

        // unlimited
        return $locations;

    }

    if( $the_limit == 0 ) {

        return array();

    }

    $the_limit = (int) $the_limit;

    $locations = array_slice($locations, 0, $the_limit);

    return $locations;

}

function rp_verify_customer_is_not_reaching_limit() {
    
    $the_limit = RP_EnhancedLocationsAddon::get_limit();

    if( $the_limit === false ) {

        // unlimited
        return TRUE;

    }

    if( $the_limit == 0 ) {

        return FALSE;

    }

    global $rpQuery;

    $rs_company_location = $rpQuery->prefix . "rs_company_location";

    $sql = "SELECT COUNT(*) FROM $rs_company_location";

    $results = $rpQuery->get_var($sql);

    if( ( (int) $results ) >= (int) $the_limit ) {

        return FALSE;

    }

    return TRUE;

}

function rp_customer_reaching_limit_verification() {

    $not_reaching_limit = rp_verify_customer_is_not_reaching_limit();

    if( $not_reaching_limit === FALSE ) {

        // Reaching limit
        echo json_encode(Array('status'=> false, 'rp_validation_error'  => 'You have reached the limit of locations you can create. Please upgrade your license to create more locations.'));

        exit;

    }

}

function rp_get_location_supported_delivery_methods( $location_id = 0 ) {

    $location_id = (int) $location_id;

    global $rpQuery;

    $rs_company_location = $rpQuery->prefix . "rs_company_location";

    $sql = "SELECT * FROM $rs_company_location WHERE `location_id` = $location_id";

    $results = $rpQuery->get_row($sql);

    $delivery_methods_db = $results->delivery_methods ?? '';

    $delivery_methods = array();

    if( !empty( $delivery_methods_db ) && !empty( trim( $delivery_methods_db ) ) ) {

        $delivery_methods_db = @json_decode( $delivery_methods_db, TRUE );

        if( !empty( $delivery_methods_db ) ) {

            $delivery_methods = $delivery_methods_db;

        }

    }

    if( empty( $delivery_methods ) ) {

        $delivery_methods = array(
            'come_by_our_store' => 1,
            'ship_device' => 1,
            'pickup_service' => 1,
            'repair_on_your_location' => 1
        );

    }

    if( ( $results->is_virtual ?? 0 ) == 1 ) {

        $delivery_methods['come_by_our_store'] = 0;
        $delivery_methods['ship_device'] = 0;
        
    }

    return $delivery_methods;

}

function rp_get_location_data_for_edit() {

    rp_verify_enhanced_location_is_active();

    rp_verify_csrf_token_for_ajax('enhanced_locations');

    rp_verify_user_full_access_ajax();

    global $rpQuery;

    $rs_company_location = $rpQuery->prefix . "rs_company_location";

    $id = (int) ($_POST['id'] ?? 0);

    $is_clone = (int) ($_POST['is_clone'] ?? FALSE);

    $_rp_company_email = rp_get_settings_company_email();

    $available_schedules = rp_get_all_schedule_groups();

    $available_schedules = rp_sanitize_output($available_schedules);

    if( empty( $id ) ) {

        rp_customer_reaching_limit_verification();

        $is_synced = !empty($_rp_company_email) ? true : false;

        $delivery_methods = array(
            'come_by_our_store' => 1,
            'ship_device' => 1,
            'pickup_service' => 1,
            'repair_on_your_location' => 1
        );

        $filtered_schedules = array();

        foreach( $available_schedules as $available_schedule ) {

            if( !empty( $available_schedule->related_to ?? '' ) ) {

                continue;

            }

            $filtered_schedules[] = $available_schedule;

        }

        $response_data = array(
            'id' => 0,
            'name' => '',
            'telephone' => '',
            'address' => '',
            'zipcode_+_city' => '',
            'google_map_link' => '',
            'email' => $_rp_company_email, 
            'bcc_email' => '',
            'schedule' => '',
            'location_head' => array(),
            'can_be_location_heads' => array(),
            'photo' => '',
            'available_schedules' => $filtered_schedules,
            'is_synced' => $is_synced,
            'is_virtual' => 0,
            'delivery_methods' => $delivery_methods
        );

        $users_who_can_become_location_head = rp_get_users_who_can_become_location_head();

        if( rp_is_enabled_pricing_based_on_location() ) {

            $response_data['can_be_location_heads'] = $users_who_can_become_location_head;

        } else {

            unset($response_data['location_head']);

            unset($response_data['can_be_location_heads']);

        }

        // it is a create form
        echo json_encode(Array('status'=> true, 'data'  => $response_data ));

        exit;

    } else {

        // verify if the location exists
        $sql = "SELECT * FROM $rs_company_location WHERE `location_id` = $id";

        $results = $rpQuery->get_row($sql);

        if( empty($results) ) {

            echo json_encode(Array('status'=> false, 'rp_validation_error'  => 'Invalid Location ID'));

            exit;

        }

        // if not empty $_rp_company_email

        $is_synced = 0;

        if( !empty( $_rp_company_email ) && ( empty( $results->location_email ) || trim( $results->location_email ) == $_rp_company_email ) ) {
                
            $is_synced = 1;
    
        }

        if( empty( $results->location_email ) ) {

            $results->location_email = $_rp_company_email;

        }

        if( $is_clone === 1 ) {
            rp_customer_reaching_limit_verification();
            $results->location_id = 0;
            $results->location_name = $results->location_name . ' (Copy)';
        }

        $delivery_methods = rp_get_location_supported_delivery_methods( $results->location_id );

        $filtered_schedules = array();

        foreach( $available_schedules as $available_schedule ) {

            if( !empty( $available_schedule->related_to ?? '' ) && $available_schedule->related_to != $id ) {

                continue;

            }

            $filtered_schedules[] = $available_schedule;

        }

        $response_data = array(
            'id' => $results->location_id,
            'name' => $results->location_name,
            'telephone' => ($results->location_telephone ?? ''),
            'address' => $results->location_address,
            'zipcode_+_city' => $results->location_city_district,
            'google_map_link' => $results->google_map_link,
            'email' => $results->location_email,
            'bcc_email' => ($results->bcc_email ?? ''),
            'schedule' => $results->schedule_group_id,
            'location_head' => array(),
            'can_be_location_heads' => array(),
            'photo' => $results->location_image,
            'available_schedules' => $filtered_schedules,
            'is_synced' => $is_synced,
            'is_virtual' => ((int)$results->is_virtual),
            'delivery_methods' => $delivery_methods
        );

        $users_who_can_become_location_head = rp_get_users_who_can_become_location_head();

        if( rp_is_enabled_pricing_based_on_location() ) {

            $response_data['location_head'] = rp_get_heads_of_location( $results->location_id );

            $response_data['can_be_location_heads'] = $users_who_can_become_location_head;

        } else {

            unset($response_data['location_head']);

            unset($response_data['can_be_location_heads']);

        }
        
        echo json_encode(Array('status'=> true, 'data'  => $response_data ));

        exit;

    }

    exit;

}

function rp_get_schedule_data_for_edit() {

    rp_verify_enhanced_location_is_active();

    rp_verify_csrf_token_for_ajax('enhanced_locations');

    global $rpQuery;

    $rs_schedule_groups = $rpQuery->prefix . "rs_schedule_groups";

    $rs_schedule_group_timing = $rpQuery->prefix . "rs_schedule_group_timing";

    $id = (int) ($_POST['id'] ?? 0);

    $is_clone = (int) ($_POST['is_clone'] ?? FALSE);

    if( $is_clone == 1 || empty( $id ) ) {

        rp_verify_user_full_access_ajax();

    }

    rp_verify_editing_schedule_group();

    if( empty( $id ) ) {

        $timings = array();

        $days = array('Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday');

        $row_data = array(
            'open_timing' => '09:00',
            'open_timing_ampm' => 'AM',
            'close_timing' => '06:00',
            'close_timing_ampm' => 'PM',
            'break_start_timing' => '01:00',
            'break_start_timing_ampm' => 'PM',
            'break_end_timing' => '02:00',
            'break_end_timing_ampm' => 'PM',
        );

        foreach($days as $theDay) {

            $row_data_copy = $row_data;

            $row_data_copy['day'] = $theDay;

            if( $theDay === 'Sunday' ) {

                $row_data_copy['open_timing'] = '';
                $row_data_copy['open_timing_ampm'] = '';
                $row_data_copy['close_timing'] = '';
                $row_data_copy['close_timing_ampm'] = '';
                $row_data_copy['break_start_timing'] = '';
                $row_data_copy['break_start_timing_ampm'] = '';
                $row_data_copy['break_end_timing'] = '';
                $row_data_copy['break_end_timing_ampm'] = '';

            }

            $timings[] = $row_data_copy;

        }

        // it is a create form
        echo json_encode(Array(
            'status'=> true, 
            'data'  => array(
                'id' => 0,
                'name' => '',
            ), 
            'timings' => $timings
        ));

        exit;

    } else {

        // verify if the location exists
        $sql = "SELECT * FROM $rs_schedule_groups WHERE `id` = $id";

        $results = $rpQuery->get_row($sql);

        if( empty($results) ) {

            echo json_encode(Array('status'=> false, 'rp_validation_error'  => 'Invalid Schedule Group ID'));

            exit;

        }

        $timings = array();

        $days = array('Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday');

        foreach( $days as $theDay ) {

            // get timing from rs_schedule_group_timing
            $sql = "SELECT * FROM `$rs_schedule_group_timing` WHERE `schedule_group_id` = $id AND `cs_day` = '$theDay'";

            $timing_results = $rpQuery->get_row($sql);

            $row_data = array(
                'day' => $theDay,
                'open_timing' => '',
                'open_timing_ampm' => '',
                'close_timing' => '',
                'close_timing_ampm' => '',
                'break_start_timing' => '',
                'break_start_timing_ampm' => '',
                'break_end_timing' => '',
                'break_end_timing_ampm' => '',
            );

            if( !empty( $timing_results ) ) {

                if( !empty( $timing_results->cs_open_timing ) ) {

                    $row_data['open_timing'] = date('h:i', strtotime($timing_results->cs_open_timing));
                    $row_data['open_timing_ampm'] = date('A', strtotime($timing_results->cs_open_timing));

                }

                if( !empty( $timing_results->cs_close_timing ) ) {

                    $row_data['close_timing'] = date('h:i', strtotime($timing_results->cs_close_timing));
                    $row_data['close_timing_ampm'] = date('A', strtotime($timing_results->cs_close_timing));

                }

                if( !empty( $timing_results->cs_breaktime_from ) ) {

                    $row_data['break_start_timing'] = date('h:i', strtotime($timing_results->cs_breaktime_from));
                    $row_data['break_start_timing_ampm'] = date('A', strtotime($timing_results->cs_breaktime_from));

                }

                if( !empty( $timing_results->cs_breaktime_to ) ) {

                    $row_data['break_end_timing'] = date('h:i', strtotime($timing_results->cs_breaktime_to));
                    $row_data['break_end_timing_ampm'] = date('A', strtotime($timing_results->cs_breaktime_to));

                }

            }

            $timings[] = $row_data;

        }

        if( $is_clone === 1 ) {
            $results->id = 0;
            $results->name = $results->name . ' (Copy)';
        }

        $results->name = rp_sanitize_output($results->name);
        
        echo json_encode(Array('status'=> true, 'data'  => array(
            'id' => $results->id,
            'name' => $results->name
        ), 'timings' => $timings));

        exit;

    }

    exit;

}

function rp_get_timings_of_schedule_group() {

    rp_verify_enhanced_location_is_active();

    rp_verify_csrf_token_for_ajax('enhanced_locations');

    global $rpQuery;

    $rs_schedule_groups = $rpQuery->prefix . "rs_schedule_groups";

    $rs_schedule_group_timing = $rpQuery->prefix . "rs_schedule_group_timing";

    $id = (int) ($_POST['id'] ?? 0);

    if( empty( $id ) ) {

        echo json_encode(Array('status'=> false, 'rp_validation_error'  => 'Invalid Schedule Group ID'));

        exit;

    } else {

        // verify if the location exists
        $sql = "SELECT * FROM $rs_schedule_groups WHERE `id` = $id";

        $results = $rpQuery->get_row($sql);

        if( empty($results) ) {

            echo json_encode(Array('status'=> false, 'rp_validation_error'  => 'Invalid Schedule Group ID'));

            exit;

        }

        $timings = array();

        $days = array('Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday');

        foreach( $days as $theDay ) {

            // get timing from rs_schedule_group_timing
            $sql = "SELECT * FROM `$rs_schedule_group_timing` WHERE `schedule_group_id` = $id AND `cs_day` = '$theDay'";

            $timing_results = $rpQuery->get_row($sql);

            $row_data = array(
                'day' => $theDay,
                'open_timing' => '',
                'open_timing_ampm' => '',
                'close_timing' => '',
                'close_timing_ampm' => '',
                'break_start_timing' => '',
                'break_start_timing_ampm' => '',
                'break_end_timing' => '',
                'break_end_timing_ampm' => '',
            );

            if( !empty( $timing_results ) ) {

                if( !empty( $timing_results->cs_open_timing ) ) {

                    $row_data['open_timing'] = date('h:i', strtotime($timing_results->cs_open_timing));
                    $row_data['open_timing_ampm'] = date('A', strtotime($timing_results->cs_open_timing));

                }

                if( !empty( $timing_results->cs_close_timing ) ) {

                    $row_data['close_timing'] = date('h:i', strtotime($timing_results->cs_close_timing));
                    $row_data['close_timing_ampm'] = date('A', strtotime($timing_results->cs_close_timing));

                }

                if( !empty( $timing_results->cs_breaktime_from ) ) {

                    $row_data['break_start_timing'] = date('h:i', strtotime($timing_results->cs_breaktime_from));
                    $row_data['break_start_timing_ampm'] = date('A', strtotime($timing_results->cs_breaktime_from));

                }

                if( !empty( $timing_results->cs_breaktime_to ) ) {

                    $row_data['break_end_timing'] = date('h:i', strtotime($timing_results->cs_breaktime_to));
                    $row_data['break_end_timing_ampm'] = date('A', strtotime($timing_results->cs_breaktime_to));

                }

            }

            $timings[] = $row_data;

        }

        $results = rp_sanitize_output($results);
        
        echo json_encode(Array('status'=> true, 'data'  => array(
            'id' => $results->id,
            'name' => $results->name
        ), 'timings' => $timings));

        exit;

    }

    exit;

}

function rp_handle_location_image_upload() {

    if(isset($_FILES) && !empty($_FILES) && isset($_FILES['location_image'])) {
        $uploadedfile = $_FILES['location_image']; 
        $upload_overrides = array( 'test_form' => false );
        $movefile = wp_handle_upload( $uploadedfile, $upload_overrides );
        if(!empty($movefile["url"])){
            $logo = $movefile["url"];
            return $logo;
        }
    }

    return ($_POST['old_location_image'] ?? '');

}

function rp_get_bcc_email_of_location( $location_id = 0 ) {

    if( rp_is_active_enhanced_locations_addon() == FALSE ) {

        // Enhanced Locations Addon is Not Active
        // So return empty
        return '';

    }

    $location_id = (int) $location_id;

    global $rpQuery;

    $rs_company_location = $rpQuery->prefix . "rs_company_location";

    $sql = "SELECT * FROM $rs_company_location WHERE `location_id` = $location_id";

    $results = $rpQuery->get_row($sql);

    if( !empty( $results ) ) {

        $result = $results->bcc_email ?? '';

        if( !empty( $result ) && filter_var($result, FILTER_VALIDATE_EMAIL) !== FALSE ) {

            return $result;

        }

    }

    return '';

}

function rp_create_or_edit_location() {

    rp_verify_enhanced_location_is_active();

    rp_verify_csrf_token_for_ajax('enhanced_locations');

    rp_verify_user_full_access_ajax();

    global $rpQuery;

    $rs_company_location = $rpQuery->prefix . "rs_company_location";

    $required_fields = array( 'name', 'telephone', 'address', 'zipcode_city', 'email', 'schedule' );

    // make sure all required fields are present
    foreach( $required_fields as $field ) {

        if( empty( $_POST[$field] ) ) {

            echo json_encode(Array('status'=> false, 'rp_validation_error'  => 'Please fill all required fields'));

            exit;

        }

    }

    $name = sanitize_text_field( $_POST['name'] ?? '' );

    $telephone = sanitize_text_field( $_POST['telephone'] ?? '' );

    $address = sanitize_text_field( $_POST['address'] ?? '' );

    $zipcode_city = sanitize_text_field( $_POST['zipcode_city'] ?? '' );

    $google_map_link = sanitize_text_field( $_POST['google_map_link'] ?? '' );

    $loc_email = sanitize_text_field( $_POST['email'] ?? '' );

    $bcc_email = sanitize_text_field( $_POST['bcc_email'] ?? '' );

    $schedule = sanitize_text_field( $_POST['schedule'] ?? '' );

    $need_to_save_location_head = false;

    $users_who_can_become_location_head = rp_get_users_who_can_become_location_head();

    if( rp_is_enabled_pricing_based_on_location() && count($users_who_can_become_location_head) > 0 ) {

        $onlyValidUserIds = array();

        foreach( $users_who_can_become_location_head as $user ) {

            $onlyValidUserIds[] = $user['ID'];

        }

        $need_to_save_location_head = true;

        $location_head = ( $_POST['location_head'] ?? array() );

        if( empty( $location_head ) ) {

            $location_head = array();

        }

        if( is_string( $location_head ) ) {

            $location_head = explode(',', $location_head);

        }

        if( !empty( $location_head ) ) {

            $location_head = array_map('intval', $location_head);

            $location_head = array_filter($location_head);

            $location_head = array_unique($location_head);

            $location_head = array_values($location_head);
            
            // make sure all selected users are valid
            foreach( $location_head as $user_id ) {

                if( !in_array( $user_id, $onlyValidUserIds ) ) {

                    echo json_encode(Array('status'=> false, 'rp_validation_error'  => 'Invalid Shop Manager'));

                    exit;

                }

            }

        }

    }

    $main_location_id = rp_get_main_location_id_of_company();

    $is_virtual = (int) ($_POST['is_virtual'] ?? 0);

    if( $is_virtual != 1 ) {

        $is_virtual = 0;

    }

    $delivery_methods_required = array(
        'come_by_our_store',
        'ship_device',
        'pickup_service',
        'repair_on_your_location'
    );

    $delivery_methods = array();

    foreach( $delivery_methods_required as $method ) {

        $delivery_methods[$method] = (int) ($_POST[$method] ?? 0);

        if( $delivery_methods[$method] != 1 ) {

            $delivery_methods[$method] = 0;

        }

    }

    if( $is_virtual == 1 ) {

        $delivery_methods['come_by_our_store'] = 0;
        $delivery_methods['ship_device'] = 0;
        
    }

    $delivery_methods = json_encode($delivery_methods);

    $location_image = rp_handle_location_image_upload();

    // make sure selected schedule is valid
    $schedule_groups = rp_get_all_schedule_groups();

    $schedule_group_ids = array();

    foreach( $schedule_groups as $schedule_group ) {

        $schedule_group_ids[] = $schedule_group->id;

    }

    if( !in_array( $schedule, $schedule_group_ids ) ) {

        echo json_encode(Array('status'=> false, 'rp_validation_error'  => 'Invalid schedule'));

        exit;

    }

    if(!empty($loc_email) && filter_var($loc_email, FILTER_VALIDATE_EMAIL) !== FALSE) {

        if( trim($loc_email) !== rp_get_settings_placeholder_email() && trim($loc_email) !== rp_get_settings_company_email() ) {

            // Skip... So It will save the email.

        } else {

            $loc_email = '';

        }

    } else {

        $loc_email = '';

    }

    if(!empty($bcc_email) && filter_var($bcc_email, FILTER_VALIDATE_EMAIL) !== FALSE) {

        // Email is good

    } else {

        $bcc_email = '';

    }

    $location_id = (int) ($_POST['id'] ?? 0);

    if( $location_id == 0 ) {

        $location_order = get_last_location_order() + 1;

        // create new location
        $sql = "INSERT INTO `$rs_company_location` (`location_name`, `location_address`, `location_city_district`, `google_map_link`, `location_email`, `schedule_group_id`, `location_image`, `location_telephone`, `is_virtual`, `delivery_methods`, `bcc_email`, `location_order`) VALUES (':name', ':address', ':zipcode_city', ':google_map_link', ':loc_email', ':schedule', ':location_image', ':telephone', ':is_virtual', ':delivery_methods', ':bcc_email', ':location_order')";

        $rpQuery->query($sql, array(
            'name' => $name,
            'address' => $address,
            'zipcode_city' => $zipcode_city,
            'google_map_link' => $google_map_link,
            'loc_email' => $loc_email,
            'bcc_email' => $bcc_email,
            'schedule' => $schedule,
            'location_image' => $location_image,
            'telephone' => $telephone,
            'is_virtual' => $is_virtual,
            'delivery_methods' => $delivery_methods,
            'location_order' => $location_order
        ));

        $insert_id = $rpQuery->insert_id;

        rp_apply_schedule_to_location($schedule, $insert_id);

        if( $need_to_save_location_head == true ) {

            rp_remove_all_location_heads_of_location( $location_id );

            rp_add_user_as_location_head_multiple( $location_id, $location_head );

        }

    } else {

        if( (int) $main_location_id == (int) $location_id ) {

            // main location cannot be virtual
            $is_virtual = 0;

        }

        // verify location id
        $verify = $rpQuery->get_row("SELECT * FROM $rs_company_location WHERE `location_id` = $location_id");

        if( empty( $verify ) ) {

            echo json_encode(Array('status'=> false, 'rp_validation_error'  => 'Invalid location ID'));

            exit;

        }

        $sql = "UPDATE `$rs_company_location` SET `location_name` = ':name', `location_address` = ':address', `location_city_district` = ':zipcode_city', `google_map_link` = ':google_map_link', `location_email` = ':loc_email', `bcc_email` = ':bcc_email', `schedule_group_id` = ':schedule', `location_image` = ':location_image', `location_telephone` = ':location_telephone', `is_virtual` = ':is_virtual', `delivery_methods` = ':delivery_methods' WHERE `location_id` = $location_id";

        $rpQuery->query($sql, array(
            'name' => $name,
            'address' => $address,
            'zipcode_city' => $zipcode_city,
            'google_map_link' => $google_map_link,
            'loc_email' => $loc_email,
            'bcc_email' => $bcc_email,
            'schedule' => $schedule,
            'location_image' => $location_image,
            'location_telephone' => $telephone,
            'is_virtual' => $is_virtual,
            'delivery_methods' => $delivery_methods
        ));

        rp_apply_schedule_to_location($schedule, $location_id);

        if( $need_to_save_location_head == true ) {

            rp_remove_all_location_heads_of_location( $location_id );

            rp_add_user_as_location_head_multiple( $location_id, $location_head );

        }

    }

    rp_register_business_profile_for_sync();

    echo json_encode(Array('status'=> true, 'message'  => 'Successfully created / updated'));

    exit;

}

function rp_create_or_edit_schedule() {

    rp_verify_enhanced_location_is_active();

    rp_verify_csrf_token_for_ajax('enhanced_locations');

    global $rpQuery;

    $rs_schedule_groups = $rpQuery->prefix . "rs_schedule_groups";

    $required_fields = array( 'name' );

    // make sure all required fields are present
    foreach( $required_fields as $field ) {

        if( empty( $_POST[$field] ) ) {

            echo json_encode(Array('status'=> false, 'rp_validation_error'  => 'Please fill all required fields'));

            exit;

        }

    }

    $name = sanitize_text_field( $_POST['name'] ?? '' );

    $schedule_group_id = (int) ($_POST['id'] ?? 0);

    if( empty( $schedule_group_id ) ) {

        rp_verify_user_full_access_ajax();

    }

    rp_verify_editing_schedule_group();

    if( !rp_current_user_has_full_access_cached() ) {

        if( rp_get_schedule_used_count( $schedule_group_id ) > 1 ) {

            echo json_encode(Array('status'=> false, 'rp_validation_error'  => 'This schedule group is in use by more than one location. You cannot edit it.'));

            exit;

        }

    }

    $cs_day = $_POST['day'] ?? array();

    $required_days = array( 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday' );

    if( empty( $cs_day ) || !is_array( $cs_day ) || count( $cs_day ) != count( $required_days ) ) {

        echo json_encode(Array('status'=> false, 'rp_validation_error'  => 'Unexpected inputs provided'));

        exit;

    }

    foreach( $required_days as $day ) {

        if( !in_array( $day, $cs_day ) ) {

            echo json_encode(Array('status'=> false, 'rp_validation_error'  => 'Unexpected inputs provided'));

            exit;

        }

    }

    $required_as_array = array( 'open_timing', 'open_timing_ampm', 'close_timing', 'close_timing_ampm', 'break_start_timing', 'break_start_timing_ampm', 'break_end_timing', 'break_end_timing_ampm' );

    foreach( $required_as_array as $field ) {

        if( empty( $_POST[$field] ?? '' ) ) {

            echo json_encode(Array('status'=> false, 'rp_validation_error'  => 'Unexpected inputs provided'));

            exit;

        }

        if( !is_array( $_POST[$field] ?? '' ) ) {

            echo json_encode(Array('status'=> false, 'rp_validation_error'  => 'Unexpected inputs provided'));

            exit;

        }

        if( count( $_POST[$field] ) != count( $required_days ) ) {

            echo json_encode(Array('status'=> false, 'rp_validation_error'  => 'Unexpected inputs provided'));

            exit;

        }

    }

    if( $schedule_group_id == 0 ) {

        // create new location
        $sql = "INSERT INTO `$rs_schedule_groups` (`name`) VALUES (':name')";

        $rpQuery->query($sql, array(
            'name' => $name,
        ));

        // insert id 
        $schedule_group_id = $rpQuery->insert_id;

    } else {

        // verify location id
        $verify = $rpQuery->get_row("SELECT * FROM $rs_schedule_groups WHERE `id` = $schedule_group_id");

        if( empty( $verify ) ) {

            echo json_encode(Array('status'=> false, 'rp_validation_error'  => 'Invalid location ID'));

            exit;

        }

        $sql = "UPDATE `$rs_schedule_groups` SET `name` = ':name' WHERE `id` = $schedule_group_id";

        $rpQuery->query($sql, array(
            'name' => $name,
        ));

    }

    // check if schedule_group_id exists in rs_schedule_group_timing
    $rs_schedule_group_timing = $rpQuery->prefix . "rs_schedule_group_timing";

    $verify = $rpQuery->get_row("SELECT * FROM $rs_schedule_group_timing WHERE `schedule_group_id` = $schedule_group_id");

    if( empty( $verify ) ) {

        foreach( $cs_day as $day_index => $day ) {

            $open_timing = sanitize_text_field( $_POST['open_timing'][$day_index] ?? '' );

            $open_timing_ampm = sanitize_text_field( $_POST['open_timing_ampm'][$day_index] ?? '' );

            $close_timing = sanitize_text_field( $_POST['close_timing'][$day_index] ?? '' );

            $close_timing_ampm = sanitize_text_field( $_POST['close_timing_ampm'][$day_index] ?? '' );

            $break_start_timing = sanitize_text_field( $_POST['break_start_timing'][$day_index] ?? '' );

            $break_start_timing_ampm = sanitize_text_field( $_POST['break_start_timing_ampm'][$day_index] ?? '' );

            $break_end_timing = sanitize_text_field( $_POST['break_end_timing'][$day_index] ?? '' );

            $break_end_timing_ampm = sanitize_text_field( $_POST['break_end_timing_ampm'][$day_index] ?? '' );

            if( empty( $open_timing ) || empty( $close_timing ) ) {

                $is_closed = 1;

                $cs_open_time = '';

                $cs_close_time = '';

                $cs_breaktime_from = '';

                $cs_breaktime_to = '';

            } else {

                $is_closed = 0;

                $cs_open_time = date( 'H:i', strtotime( $open_timing . ' ' . $open_timing_ampm ) );

                $cs_close_time = date( 'H:i', strtotime( $close_timing . ' ' . $close_timing_ampm ) );

                if( !empty( $break_start_timing ) ) {

                    $cs_breaktime_from = date( 'H:i', strtotime( $break_start_timing . ' ' . $break_start_timing_ampm ) );

                } else {

                    $cs_breaktime_from = '';

                }

                if( !empty( $break_end_timing ) ) {

                    $cs_breaktime_to = date( 'H:i', strtotime( $break_end_timing . ' ' . $break_end_timing_ampm ) );

                } else {

                    $cs_breaktime_to = '';

                }

            }

            $sql = "INSERT INTO `$rs_schedule_group_timing` (`schedule_group_id`, `cs_day`, `cs_open_timing`, `cs_close_timing`, `cs_breaktime_from`, `cs_breaktime_to`, `is_closed`) VALUES (':schedule_group_id', ':cs_day', ':cs_open_time', ':cs_close_time', ':cs_breaktime_from', ':cs_breaktime_to', ':is_closed')";

            $rpQuery->query($sql, array(
                'schedule_group_id' => $schedule_group_id,
                'cs_day' => $day,
                'cs_open_time' => $cs_open_time,
                'cs_close_time' => $cs_close_time,
                'cs_breaktime_from' => $cs_breaktime_from,
                'cs_breaktime_to' => $cs_breaktime_to,
                'is_closed' => $is_closed,
            ));

        }

    } else {

        foreach( $cs_day as $day_index => $day ) {

            $open_timing = sanitize_text_field( $_POST['open_timing'][$day_index] ?? '' );

            $open_timing_ampm = sanitize_text_field( $_POST['open_timing_ampm'][$day_index] ?? '' );

            $close_timing = sanitize_text_field( $_POST['close_timing'][$day_index] ?? '' );

            $close_timing_ampm = sanitize_text_field( $_POST['close_timing_ampm'][$day_index] ?? '' );

            $break_start_timing = sanitize_text_field( $_POST['break_start_timing'][$day_index] ?? '' );

            $break_start_timing_ampm = sanitize_text_field( $_POST['break_start_timing_ampm'][$day_index] ?? '' );

            $break_end_timing = sanitize_text_field( $_POST['break_end_timing'][$day_index] ?? '' );

            $break_end_timing_ampm = sanitize_text_field( $_POST['break_end_timing_ampm'][$day_index] ?? '' );

            if( empty( $open_timing ) || empty( $close_timing ) ) {

                $is_closed = 1;

                $cs_open_time = '';

                $cs_close_time = '';

                $cs_breaktime_from = '';

                $cs_breaktime_to = '';

            } else {

                $is_closed = 0;

                $cs_open_time = date( 'H:i', strtotime( $open_timing . ' ' . $open_timing_ampm ) );

                $cs_close_time = date( 'H:i', strtotime( $close_timing . ' ' . $close_timing_ampm ) );

                if( !empty( $break_start_timing ) ) {

                    $cs_breaktime_from = date( 'H:i', strtotime( $break_start_timing . ' ' . $break_start_timing_ampm ) );

                } else {

                    $cs_breaktime_from = '';

                }

                if( !empty( $break_end_timing ) ) {

                    $cs_breaktime_to = date( 'H:i', strtotime( $break_end_timing . ' ' . $break_end_timing_ampm ) );

                } else {

                    $cs_breaktime_to = '';

                }

            }

            $sql = "UPDATE `$rs_schedule_group_timing` SET `cs_open_timing` = ':cs_open_time', `cs_close_timing` = ':cs_close_time', `cs_breaktime_from` = ':cs_breaktime_from', `cs_breaktime_to` = ':cs_breaktime_to', `is_closed` = ':is_closed' WHERE `schedule_group_id` = ':schedule_group_id' AND `cs_day` = ':cs_day'";

            $rpQuery->query($sql, array(
                'cs_open_time' => $cs_open_time,
                'cs_close_time' => $cs_close_time,
                'cs_breaktime_from' => $cs_breaktime_from,
                'cs_breaktime_to' => $cs_breaktime_to,
                'is_closed' => $is_closed,
                'cs_day' => $day,
                'schedule_group_id' => $schedule_group_id,
            ));

        }

    }

    rp_update_all_locations_using_this_schedule( $schedule_group_id );

    echo json_encode(Array('status'=> true, 'message'  => 'Successfully created / updated'));

    exit;

}

function rp_update_all_locations_using_this_schedule( $schedule_group_id = 0 ) {

    if( empty( $schedule_group_id ) ) {

        return;

    }

    $schedule_group_id = (int) $schedule_group_id;

    global $rpQuery;

    $rs_company_location = $rpQuery->prefix . "rs_company_location";

    // get all locations that are using this schedule

    $locations = $rpQuery->get_results("SELECT * FROM `$rs_company_location` WHERE `schedule_group_id` = $schedule_group_id");

    // If not empty locations, loop through all location_row and rp_apply_schedule_to_location
    if( !empty( $locations ) ) {

        foreach( $locations as $location_row ) {

            rp_apply_schedule_to_location( $schedule_group_id, $location_row->location_id );
    
        }

    }

    rp_register_business_profile_for_sync();

    return true;

}

function rp_delete_enhanced_location() {

    rp_verify_enhanced_location_is_active();

    rp_verify_csrf_token_for_ajax('enhanced_locations');

    rp_verify_user_full_access_ajax();

    global $rpQuery;

    $rs_company_location = $rpQuery->prefix . "rs_company_location";

    $rs_company_schedules = $rpQuery->prefix . "rs_company_schedules";

    $location_id = (int) ($_POST['id'] ?? 0);

    if( $location_id == 0 ) {

        echo json_encode(Array('status'=> false, 'rp_validation_error'  => 'Invalid location ID'));

        exit;

    }

    // verify location id
    $verify = $rpQuery->get_row("SELECT * FROM $rs_company_location WHERE `location_id` = $location_id");

    if( empty( $verify ) ) {

        echo json_encode(Array('status'=> false, 'rp_validation_error'  => 'Invalid location ID'));

        exit;

    }

    // make sure we will still have at least one location row after deleting this one
    $locations = $rpQuery->get_results("SELECT * FROM $rs_company_location");

    if( count( $locations ) == 1 ) {

        echo json_encode(Array('status'=> false, 'rp_validation_error'  => 'You must keep at least one location'));

        exit;

    }

    $rpQuery->query("DELETE FROM `$rs_company_location` WHERE `location_id` = $location_id");

    $rpQuery->query("DELETE FROM `$rs_company_schedules` WHERE `location_id_fk` = $location_id");

    echo json_encode(Array('status'=> true, 'message'  => 'Successfully deleted'));

    exit;


}

function rp_update_schedule_group_of_location() {

    rp_verify_enhanced_location_is_active();

    rp_verify_csrf_token_for_ajax('enhanced_locations');

    rp_verify_user_full_access_ajax();

    $id = (int) ($_POST['id'] ?? 0);

    $schedule = (int) ($_POST['value'] ?? 0);

    if( $id == 0 || $schedule == 0 ) {

        echo json_encode(Array('status'=> false, 'rp_validation_error'  => 'Invalid location ID or schedule ID'));

        exit;

    }

    global $rpQuery;

    $rs_company_location = $rpQuery->prefix . "rs_company_location";

    $available_schedules = rp_get_all_schedule_groups();

    // make sure the schedule id is valid
    if( !empty( $available_schedules ) ) {

        $schedule_group_ids = array();

        foreach( $available_schedules as $schedule_group ) {

            $schedule_group_ids[] = $schedule_group->id;

        }

    } else {

        $schedule_group_ids = array();

    }

    if( !in_array( $schedule, $schedule_group_ids ) ) {

        echo json_encode(Array('status'=> false, 'rp_validation_error'  => 'Invalid schedule ID'));

        exit;

    }

    // make sure the location id is valid
    $verify = $rpQuery->get_row("SELECT * FROM $rs_company_location WHERE `location_id` = $id");

    if( empty( $verify ) ) {

        echo json_encode(Array('status'=> false, 'rp_validation_error'  => 'Invalid location ID'));

        exit;

    }

    $rpQuery->query("UPDATE `$rs_company_location` SET `schedule_group_id` = $schedule WHERE `location_id` = $id");

    rp_apply_schedule_to_location( $schedule, $id );

    rp_register_business_profile_for_sync();

    echo json_encode(Array('status'=> true, 'message'  => 'Successfully updated'));

    exit;

}

function rp_enhanced_locations_addon_initialize() {
  
    rp_ajax_for_admin('rp_delete_schedule_group','rp_delete_schedule_group');

    rp_ajax_for_admin('rp_deleting_schedule_group','rp_deleting_schedule_group');

    rp_ajax_for_admin('rp_deleting_location','rp_deleting_location');

    rp_ajax_for_admin('rp_get_location_data_for_edit', 'rp_get_location_data_for_edit');

    rp_ajax_for_admin('rp_get_schedule_data_for_edit', 'rp_get_schedule_data_for_edit');

    // Need to rp_apply_schedule_to_location
    rp_ajax_for_admin('rp_create_or_edit_location', 'rp_create_or_edit_location');

    // Need to rp_apply_schedule_to_location
    rp_ajax_for_admin('rp_create_or_edit_schedule', 'rp_create_or_edit_schedule');

    rp_ajax_for_admin('rp_delete_enhanced_location', 'rp_delete_enhanced_location');

    // Need to rp_apply_schedule_to_location
    rp_ajax_for_admin('rp_update_schedule_group_of_location', 'rp_update_schedule_group_of_location');

    rp_ajax_for_admin('rp_get_timings_of_schedule_group', 'rp_get_timings_of_schedule_group');

    rp_ajax_for_public('rp_search_nearest_locations', 'rp_search_nearest_locations');

    rp_ajax_for_public('rp_search_nearest_preselect_locations', 'rp_search_nearest_preselect_locations');

    rp_ajax_for_public('rp_get_place_autocomplete_suggestions', 'rp_get_place_autocomplete_suggestions');

}

rp_add_action('rp_enhanced_locations_initialize', 'rp_enhanced_locations_addon_initialize');


function rp_get_all_company_locations( $current_page = 0, $limit = 0, $where_sql = '' ) {

    global $rpQuery;

    $offset = 0;

    if( $current_page > 0 ) {

        $offset = ( $current_page - 1 ) * $limit;

    }

    $rs_company_location = $rpQuery->prefix . "rs_company_location";

    $sql = "SELECT * FROM (SELECT *,
    CASE WHEN `location_email` IS NOT NULL AND `location_email` != '' THEN
    CONCAT(`location_name`, ' ', `location_email`, ' ', `location_address`, ' ', `location_city_district`, `location_telephone`)
    ELSE
    CONCAT(`location_name`, ' ', '".rp_get_settings_company_email()."', ' ', `location_address`, ' ', `location_city_district`, `location_telephone`) END AS `search_text`
    FROM $rs_company_location) AS subquery";

    $sql .= " {$where_sql}";

    // order by location_order and location_id
    $sql .= " ORDER BY `location_order` ASC, `location_id` ASC";

    // Add limit and offset

    if( $limit > 0 ) {

        $sql .= " LIMIT $limit";

    }

    if( $offset > 0 ) {

        $sql .= " OFFSET $offset";

    }

    $results = $rpQuery->get_results($sql);

    if( !empty($results) ) {

        return $results;

    }

    return array();

}

function rp_get_schedule_used_count( $schedule_id = 0 ) {

    global $rpQuery;

    $rs_company_location = $rpQuery->prefix . "rs_company_location";

    $sql = "SELECT COUNT(*) FROM $rs_company_location WHERE `schedule_group_id` = $schedule_id";

    $results = $rpQuery->get_var($sql);

    if( !empty($results) ) {

        return $results;

    }

    return 0;


}

function rp_get_total_company_locations( $where_sql = '' ) {

    global $rpQuery;

    $rs_company_location = $rpQuery->prefix . "rs_company_location";

    $sql = "SELECT * FROM (SELECT *,
    CASE WHEN `location_email` IS NOT NULL AND `location_email` != '' THEN
    CONCAT(`location_name`, ' ', `location_email`, ' ', `location_address`, ' ', `location_city_district`, `location_telephone`)
    ELSE
    CONCAT(`location_name`, ' ', '".rp_get_settings_company_email()."', ' ', `location_address`, ' ', `location_city_district`, `location_telephone`) END AS `search_text`
    FROM $rs_company_location) AS subquery";

    $sql .= " {$where_sql}";

    $results = $rpQuery->get_results($sql);

    if( !empty($results) ) {

        return count($results);

    }

    return 0;

}

function rp_add_schedule_group_column_to_location_table() {

    if( function_exists('rp_add_column_to_table_if_not_exists') ) {

        if( rp_is_active_enhanced_locations_addon() === TRUE ) {

            rp_autocreate_schedule_groups_first_time();

        }

    }

}

rp_add_action('init', 'rp_add_schedule_group_column_to_location_table', 9999);


function rp_apply_schedule_to_location( $schedule_id = 0, $location_id = 0 ) {

    // if empty schedule_id or location_id, return false
    if( empty($schedule_id) || empty($location_id) ) {

        return false;

    }

    global $rpQuery;

    $rs_schedule_groups = $rpQuery->prefix . "rs_schedule_groups";

    $rs_schedule_group_timing = $rpQuery->prefix . "rs_schedule_group_timing";

    $rs_company_location = $rpQuery->prefix . "rs_company_location";

    $rs_company_schedules = $rpQuery->prefix . "rs_company_schedules";

    // get schedule group
    $schedule_group = $rpQuery->get_row("SELECT * FROM `$rs_schedule_groups` WHERE `id` = $schedule_id");

    // get timing of schedule group
    $schedule_group_timing = $rpQuery->get_results("SELECT * FROM `$rs_schedule_group_timing` WHERE `schedule_group_id` = $schedule_id");

    // get location
    $location = $rpQuery->get_row("SELECT * FROM `$rs_company_location` WHERE `location_id` = $location_id");

    // make sure $schedule_group, $schedule_group_timing and $location are not empty
    if( empty($schedule_group) || empty($schedule_group_timing) || empty($location) ) {

        return false;

    }

    // loop through all schedule group timing
    foreach( $schedule_group_timing as $timing_row ) {

        $cs_day = $timing_row->cs_day;

        $cs_open_timing = $timing_row->cs_open_timing;

        $cs_close_timing = $timing_row->cs_close_timing;

        $cs_breaktime_from = $timing_row->cs_breaktime_from;

        $cs_breaktime_to = $timing_row->cs_breaktime_to;

        $is_closed = $timing_row->is_closed;

        $exists = $rpQuery->get_row("SELECT * FROM `$rs_company_schedules` WHERE `location_id_fk` = $location_id AND `cs_day` = '{$cs_day}'");

        if( !empty( $exists ) ) {

            // Need to update
            $update_id = $exists->cs_id;

            // update cs_day, cs_open_timing, cs_close_timing, cs_breaktime_from, cs_breaktime_to, is_closed
            $rpQuery->query("UPDATE `$rs_company_schedules` SET `cs_day` = '{$cs_day}', `cs_open_timing` = '{$cs_open_timing}', `cs_close_timing` = '{$cs_close_timing}', `cs_breaktime_from` = '{$cs_breaktime_from}', `cs_breaktime_to` = '{$cs_breaktime_to}', `is_closed` = '{$is_closed}' WHERE `cs_id` = $update_id");

        } else {

            // Need to create
            $rpQuery->query("INSERT INTO `$rs_company_schedules` (`location_id_fk`, `cs_day`, `cs_open_timing`, `cs_close_timing`, `cs_breaktime_from`, `cs_breaktime_to`, `is_closed`) VALUES ('$location_id', '{$cs_day}', '{$cs_open_timing}', '{$cs_close_timing}', '{$cs_breaktime_from}', '{$cs_breaktime_to}', '{$is_closed}')");

        }

    }

    // update business_profile_synced on rs_company_location to be 0
    $rpQuery->query("UPDATE `$rs_company_location` SET `business_profile_synced` = 0 WHERE `location_id` = $location_id");

    return true;

}

function rp_getting_special_schedule_filter( $schedules = array(), $loc_id = 0, $day = '', $date_ymd = '' ) {

    if( rp_is_active_enhanced_locations_addon() === false ) {

        return $schedules;

    }

    global $rpQuery;

    $rs_company_schedules = $rpQuery->prefix . "rs_company_schedules";

    $rs_company_location = $rpQuery->prefix . "rs_company_location";

    $rs_schedule_groups = $rpQuery->prefix . "rs_schedule_groups";

    $rs_schedule_group_timing = $rpQuery->prefix . "rs_schedule_group_timing";

    // select * from rs_company_location where location_id = $loc_id
    $location = $rpQuery->get_row("SELECT * FROM `$rs_company_location` WHERE `location_id` = $loc_id");

    $schedule_group_id = 0;

    $schedule_group_timing = array();

    if( !empty( $location ) ) {

        $schedule_group_id = $location->schedule_group_id ?? 0;

        if( !empty( $schedule_group_id ) ) {

            // make sure schedule_group_id is not empty and exists in rs_schedule_groups table
            $exists_group = $rpQuery->get_row("SELECT * FROM `$rs_schedule_groups` WHERE `id` = $schedule_group_id");

            if( !empty( $exists_group ) ) {

                // get timing of schedule group
                $schedule_group_timing = $rpQuery->get_results("SELECT * FROM `$rs_schedule_group_timing` WHERE `schedule_group_id` = $schedule_group_id AND `cs_day` = '".rp_escape_sql($day)."'");

            }

        }

    }

    // get only m-d of Y-m-d format from $date_ymd
    $date_md = explode('-', $date_ymd);
    $date_md = $date_md[1] . '-' . $date_md[2];

    $result = rp_get_special_timing( $date_md, $loc_id );

    if( !empty( $schedule_group_id ) ) {

        $special_schedule_timing = rp_get_special_timing( $date_md, 'sg_' . $schedule_group_id );

    } else {

        $special_schedule_timing = array();

    }

    // If have special schedule related to location return it

    // If have special schedule related to schedule group return it

    // If have schedule group timing return it

    // Else return normal schedule

    $org_schedules = $rpQuery->get_row("SELECT * FROM `$rs_company_schedules` WHERE `cs_day` = '".rp_escape_sql($day)."' AND `location_id_fk` = '".rp_escape_sql($loc_id)."' LIMIT 1");

    $is_originally_closed = 0;

    if( !empty( $schedule_group_timing ) ) {

        $is_originally_closed = $schedule_group_timing[0]->is_closed ?? 0;

    } else {

        $is_originally_closed = $org_schedules->is_closed ?? 0;

    }

    // If special timing is there and close, consider it
    // Otherwise for special timing to be considered, it must be there and original schedule must not be closed!

    if( !empty( $result ) && ( ( $result->is_closed ?? 0 ) == 1 || $is_originally_closed == 0 ) ) {

        $result->cs_day = $day;

        $result->reminder_name = rp_get_static_translations_of_special_date_name_selected('reminder_name', $result->cs_id, 'selected');

        $schedules = array($result);

    } else if( !empty( $special_schedule_timing ) && ( ( $special_schedule_timing->is_closed ?? 0 ) == 1 || $is_originally_closed == 0 ) ) {

        $special_schedule_timing->cs_day = $day;

        $special_schedule_timing->reminder_name = rp_get_static_translations_of_special_date_name_selected('reminder_name', $special_schedule_timing->cs_id, 'selected');

        $schedules = array($special_schedule_timing);

    } else if( !empty( $schedule_group_timing ) ) {

        $schedules = $schedule_group_timing;

    } else {

        $schedules = array( $org_schedules );

    }

    return $schedules;

}

add_filter('rp_getting_special_schedule_filter', 'rp_getting_special_schedule_filter', 10, 4);

function rp_getting_only_normal_schedule_filter( $schedules = array(), $loc_id = 0, $day = '', $date_ymd = '' ) {

    if( rp_is_active_enhanced_locations_addon() === false ) {

        return $schedules;

    }

    global $rpQuery;

    $rs_company_schedules = $rpQuery->prefix . "rs_company_schedules";

    $rs_company_location = $rpQuery->prefix . "rs_company_location";

    $rs_schedule_groups = $rpQuery->prefix . "rs_schedule_groups";

    $rs_schedule_group_timing = $rpQuery->prefix . "rs_schedule_group_timing";

    // select * from rs_company_location where location_id = $loc_id
    $location = $rpQuery->get_row("SELECT * FROM `$rs_company_location` WHERE `location_id` = $loc_id");

    $schedule_group_id = 0;

    $schedule_group_timing = array();

    if( !empty( $location ) ) {

        $schedule_group_id = $location->schedule_group_id ?? 0;

        if( !empty( $schedule_group_id ) ) {

            // make sure schedule_group_id is not empty and exists in rs_schedule_groups table
            $exists_group = $rpQuery->get_row("SELECT * FROM `$rs_schedule_groups` WHERE `id` = $schedule_group_id");

            if( !empty( $exists_group ) ) {

                // get timing of schedule group
                $schedule_group_timing = $rpQuery->get_results("SELECT * FROM `$rs_schedule_group_timing` WHERE `schedule_group_id` = $schedule_group_id AND `cs_day` = '".rp_escape_sql($day)."'");

            }

        }

    }

    $org_schedules = $rpQuery->get_row("SELECT * FROM `$rs_company_schedules` WHERE `cs_day` = '".rp_escape_sql($day)."' AND `location_id_fk` = '".rp_escape_sql($loc_id)."' LIMIT 1");

    if( !empty( $schedule_group_timing ) ) {

        $schedules = $schedule_group_timing;

    } else {

        $schedules = array( $org_schedules );

    }

    return $schedules;

}

add_filter('rp_getting_only_normal_schedule_filter', 'rp_getting_only_normal_schedule_filter', 10, 4);

function rp_get_main_location_id_of_company() {

    global $rpQuery;

    $rs_company_location = $rpQuery->prefix . "rs_company_location";

    // return first location of company

    $location = $rpQuery->get_row("SELECT `location_id` FROM `$rs_company_location` ORDER BY `location_id` ASC LIMIT 1;");

    if( !empty( $location ) ) {

        return $location->location_id;

    }

    return 0;

}

function rp_autocreate_schedule_groups_first_time() {

    // check if schedule groups already exists
    $schedule_groups = rp_get_all_schedule_groups();

    if( !empty( $schedule_groups ) ) {

        // Already exists so do not do anything

        return;

    }

    global $rpQuery;
    
    $rs_company_location = $rpQuery->prefix . "rs_company_location";

    $rs_company_schedules = $rpQuery->prefix . "rs_company_schedules";

    $rs_schedule_groups = $rpQuery->prefix . "rs_schedule_groups";

    $rs_schedule_group_timing = $rpQuery->prefix . "rs_schedule_group_timing";

    $created_schedule_ids = array();

    // get all locations from rs_company_location

    $locations = $rpQuery->get_results("SELECT * FROM `$rs_company_location`");

    if( !empty( $locations ) ) {

        // loop through all locations and get the schedules of that location in rs_company_schedules (location_id_fk)
        foreach( $locations as $the_location_row ) {

            $location_schedules = $rpQuery->get_results("SELECT * FROM `$rs_company_schedules` WHERE `location_id_fk` = {$the_location_row->location_id}");

            // loop through all location_schedules

            $unique_id = '';

            foreach( $location_schedules as $theTimingRow ) {

                // cs_day, cs_open_timing, cs_close_timing, cs_breaktime_from, cs_breaktime_to, is_closed

                $unique_id .= $theTimingRow->cs_day . $theTimingRow->cs_open_timing . $theTimingRow->cs_close_timing . $theTimingRow->cs_breaktime_from . $theTimingRow->cs_breaktime_to . $theTimingRow->is_closed;

            }

            $unique_id = md5( $unique_id );

            if( !isset( $created_schedule_ids [ $unique_id ] ) )  {
                
                // Schedule doesn't match so need to create new schedule group
                $schedule_group_name = $the_location_row->location_name . ' (Schedule)';

                // insert into rs_schedule_groups (`name`)
                $rpQuery->query("INSERT INTO `$rs_schedule_groups` (`name`) VALUES ('".rp_escape_sql($schedule_group_name)."')");

                $schedule_group_id = $rpQuery->insert_id;

                foreach( $location_schedules as $theTimingRow ) {

                    if( $theTimingRow->is_closed == 1 ) {

                        $theTimingRow->cs_open_timing = '';

                        $theTimingRow->cs_close_timing = '';

                        $theTimingRow->cs_breaktime_from = '';

                        $theTimingRow->cs_breaktime_to = '';

                    }

                    $rpQuery->query("INSERT INTO `$rs_schedule_group_timing` (`schedule_group_id`, `cs_day`, `cs_open_timing`, `cs_close_timing`, `cs_breaktime_from`, `cs_breaktime_to`, `is_closed`) VALUES ('".rp_escape_sql($schedule_group_id)."', '".rp_escape_sql($theTimingRow->cs_day)."', '".rp_escape_sql($theTimingRow->cs_open_timing)."', '".rp_escape_sql($theTimingRow->cs_close_timing)."', '".rp_escape_sql($theTimingRow->cs_breaktime_from)."', '".rp_escape_sql($theTimingRow->cs_breaktime_to)."', '".rp_escape_sql($theTimingRow->is_closed)."')");

                }

                // assign schedule to location
                $rpQuery->query("UPDATE `$rs_company_location` SET `schedule_group_id` = '".rp_escape_sql($schedule_group_id)."' WHERE `location_id` = '".rp_escape_sql($the_location_row->location_id)."'");

                $created_schedule_ids[ $unique_id ] = $schedule_group_id;

            } else {

                // Schedule matches, so just assign to the location
                $schedule_group_id = $created_schedule_ids[ $unique_id ];

                // assign schedule to location
                $rpQuery->query("UPDATE `$rs_company_location` SET `schedule_group_id` = '".rp_escape_sql($schedule_group_id)."' WHERE `location_id` = '".rp_escape_sql($the_location_row->location_id)."'");

            }

        }

    }

}

function rp_get_location_autocomplete_suggestions( $address = '' ) {

    global $rpQuery;

    require_once RP_EL_PLUGIN_PATH . 'classes/RP_Maps_API.php';

    $maps_api = new RepairPluginPro\RP_Maps_API( $rpQuery );

    $address = $maps_api->fix_address( trim( $address ) );

    // if address is too short, skip
    if( strlen( $address ) <= 6 ) {

        return false;

    }

    $response = $maps_api->get_autocomplete_suggestions( $address );

    if( $response !== false ) {

        return $response;

    }

    return false;

}

function rp_get_location_longitude_and_latitude( $address = '' ) {

    global $rpQuery;

    require_once RP_EL_PLUGIN_PATH . 'classes/RP_Maps_API.php';

    $maps_api = new RepairPluginPro\RP_Maps_API( $rpQuery );

    $address = $maps_api->fix_address( trim( $address ) );

    // if address is too short, skip
    if( strlen( $address ) <= 6 ) {

        return false;

    }

    $response = $maps_api->get_lat_long( $address );

    if( $response !== false ) {

        return $response;

    }

    return false;

}

function rp_get_location_formatted_address( $latlng = '' ) {

    global $rpQuery;

    require_once RP_EL_PLUGIN_PATH . 'classes/RP_Maps_API.php';

    $maps_api = new RepairPluginPro\RP_Maps_API( $rpQuery );

    $response = $maps_api->get_formatted_address( $latlng );

    if( $response !== false ) {

        return $response;

    }

    return false;

}

function rp_set_based_on_location( $order_id = 0, $parent_order_id = 0 ) {

    $order_id = (int) $order_id;

    $parent_order_id = (int) $parent_order_id;

    global $rpQuery;

    $rs_orders = $rpQuery->prefix . 'rs_orders';

    $based_on_location = 0;

    if( rp_is_enabled_pricing_based_on_location() == TRUE ) {

        $based_on_location = 1;

    }

    if( !empty( $parent_order_id ) ) {

        // get parent order row
        $row = $rpQuery->get_row("SELECT * FROM `$rs_orders` WHERE `o_id` = $parent_order_id");

        if( !empty( $row ) ) {

            $based_on_location = (int) ($row->based_on_location ?? 0);

        }

    }

    $rpQuery->query("UPDATE `$rs_orders` SET `based_on_location` = $based_on_location WHERE `o_id` = $order_id");

}

function rp_get_lat_long_of_location( $location_id = '' ) {

    global $rpQuery;

    $rs_company_location = $rpQuery->prefix . "rs_company_location";

    // make sure location exists
    $location_row = $rpQuery->get_row("SELECT * FROM `$rs_company_location` WHERE `location_id` = '".rp_escape_sql($location_id)."'");

    if( !empty( $location_row ) ) {

        $address = trim( $location_row->location_address . ' ' . $location_row->location_city_district );

        return rp_get_location_longitude_and_latitude( $address );

    }

    return false;

}

function rp_cache_locations_latlong_if_not_already() {

    $rp_el_google_maps_api_key = rp_get_option('rp_el_google_maps_api_key', '');

    $rp_enable_search_by_nearest_location = rp_get_option('rp_enable_search_by_nearest_location', '1');

    if( empty( $rp_el_google_maps_api_key ) || $rp_enable_search_by_nearest_location != '1' ) {

        return;

    }

    global $rpQuery;

    require_once RP_EL_PLUGIN_PATH . 'classes/RP_Maps_API.php';

    $maps_api = new RepairPluginPro\RP_Maps_API( $rpQuery );

    $rs_company_location = $rpQuery->prefix . "rs_company_location";

    $locations = $rpQuery->get_results("SELECT * FROM `$rs_company_location`");

    foreach( $locations as $location_row ) {

        $address = trim( $location_row->location_address . ' ' . $location_row->location_city_district );

        $address = $maps_api->fix_address( $address );

        // if address is too short, skip
        if( strlen( $address ) <= 6 ) {

            continue;

        }

        $response = $maps_api->get_cached_response( 'lat_long', $address );

        if( empty( $response ) ) {

            $response = $maps_api->get_lat_long( $address );

            return;

        }

    }

}

rp_add_action('rp_enhanced_locations_initialize', 'rp_cache_locations_latlong_if_not_already', 9999);

function rp_filter_locations_with_come_our_store_enabled( $locations = array() ) {

    if( rp_is_active_enhanced_locations_addon() == FALSE || rp_is_enabled_pricing_based_on_location() == TRUE ) {
            
        return $locations;

    }

    if( !empty( $locations ) ) {

        foreach( $locations as $locKey => $theLocation ) {

            $supported_delivery_methods = rp_get_location_supported_delivery_methods( $theLocation->location_id );

            if( !empty( $supported_delivery_methods ) && $supported_delivery_methods['come_by_our_store'] == 1 ) {

                // this location supports come our store

            } else {

                // this location does not support come our store, so remove it from locations array
                unset( $locations[ $locKey ] );

            }

        }

        // reindex array
        $locations = array_values( $locations );

    }

    return $locations;

}

function rp_add_filter_come_our_store_locations() {

    add_filter('rp_filter_nearest_locations_before_process', 'rp_filter_locations_with_come_our_store_enabled', 10, 1);

}

function rp_remove_filter_come_our_store_locations() {

    remove_filter('rp_filter_nearest_locations_before_process', 'rp_filter_locations_with_come_our_store_enabled', 10, 1);

}

function rp_filter_locations_with_ship_device_enabled( $locations = array() ) {

    if( rp_is_active_enhanced_locations_addon() == FALSE || rp_is_enabled_pricing_based_on_location() == TRUE ) {
            
        return $locations;

    }

    if( !empty( $locations ) ) {

        foreach( $locations as $locKey => $theLocation ) {

            $supported_delivery_methods = rp_get_location_supported_delivery_methods( $theLocation->location_id );

            if( !empty( $supported_delivery_methods ) && $supported_delivery_methods['ship_device'] == 1 ) {

                // this location supports ship device

            } else {

                // this location does not support ship device, so remove it from locations array
                unset( $locations[ $locKey ] );

            }

        }

        // reindex array
        $locations = array_values( $locations );

    }

    return $locations;

}

function rp_add_filter_ship_device_locations() {

    add_filter('rp_filter_nearest_locations_before_process', 'rp_filter_locations_with_ship_device_enabled', 10, 1);

}

function rp_remove_filter_ship_device_locations() {

    remove_filter('rp_filter_nearest_locations_before_process', 'rp_filter_locations_with_ship_device_enabled', 10, 1);

}

function rp_filter_locations_with_pickup_service_enabled( $locations = array() ) {

    if( rp_is_active_enhanced_locations_addon() == FALSE || rp_is_enabled_pricing_based_on_location() == TRUE ) {
            
        return $locations;

    }

    if( !empty( $locations ) ) {

        foreach( $locations as $locKey => $theLocation ) {

            $supported_delivery_methods = rp_get_location_supported_delivery_methods( $theLocation->location_id );

            if( !empty( $supported_delivery_methods ) && $supported_delivery_methods['pickup_service'] == 1 ) {

                // this location supports ship device

            } else {

                // this location does not support ship device, so remove it from locations array
                unset( $locations[ $locKey ] );

            }

        }

        // reindex array
        $locations = array_values( $locations );

    }

    return $locations;

}

function rp_add_filter_pickup_service_locations() {

    add_filter('rp_filter_nearest_locations_before_process', 'rp_filter_locations_with_pickup_service_enabled', 10, 1);

}

function rp_remove_filter_pickup_service_locations() {

    remove_filter('rp_filter_nearest_locations_before_process', 'rp_filter_locations_with_pickup_service_enabled', 10, 1);

}

function rp_filter_locations_with_repair_on_your_location_enabled( $locations = array() ) {

    if( rp_is_active_enhanced_locations_addon() == FALSE || rp_is_enabled_pricing_based_on_location() == TRUE ) {
            
        return $locations;

    }

    if( !empty( $locations ) ) {

        foreach( $locations as $locKey => $theLocation ) {

            $supported_delivery_methods = rp_get_location_supported_delivery_methods( $theLocation->location_id );

            if( !empty( $supported_delivery_methods ) && $supported_delivery_methods['repair_on_your_location'] == 1 ) {

                // this location supports ship device

            } else {

                // this location does not support ship device, so remove it from locations array
                unset( $locations[ $locKey ] );

            }

        }

        // reindex array
        $locations = array_values( $locations );

    }

    return $locations;

}

function rp_add_filter_repair_on_your_location_locations() {

    add_filter('rp_filter_nearest_locations_before_process', 'rp_filter_locations_with_repair_on_your_location_enabled', 10, 1);

}

function rp_remove_filter_repair_on_your_location_locations() {

    remove_filter('rp_filter_nearest_locations_before_process', 'rp_filter_locations_with_repair_on_your_location_enabled', 10, 1);

}

function rp_sort_locations_by_nearest_radius_distance( $input_lat_lng = array() ) {

    if( !empty( $input_lat_lng ) && is_string( $input_lat_lng ) ) {

        $input_lat_lng = explode(',', $input_lat_lng);

    }

    global $rpQuery;

    require_once RP_EL_PLUGIN_PATH . 'classes/RP_Maps_API.php';

    $maps_api = new RepairPluginPro\RP_Maps_API( $rpQuery );

    $rs_company_location = $rpQuery->prefix . "rs_company_location";

    // Get all locations
    $locations = $rpQuery->get_results("SELECT * FROM `$rs_company_location` ORDER BY `location_order` ASC, `location_id` ASC");

    $enabled_virtual_location = rp_is_enabled_virtual_location();

    $exclude_virtual_location = apply_filters('rp_exclude_virtual_location', TRUE);

    if( $enabled_virtual_location !== FALSE && $exclude_virtual_location == TRUE ) {

        // only show those locations that are not virtual

        $exc_virtual = array();

        foreach($locations as $loc) {
            if( $loc->is_virtual == '0' ) {
                $exc_virtual[] = $loc;
            }
        }

        $locations = $exc_virtual;

    }

    $locations = rp_el_apply_limit_to_locations( $locations );

    $locations = apply_filters('rp_filter_nearest_locations_before_process', $locations);

    if( empty( $input_lat_lng ) || !is_array( $input_lat_lng ) || count( $input_lat_lng ) != 2 ) {

        return $locations;

    }

    if( !empty( $locations ) ) {

        $found_lat_lng = array();

        $unfound_lat_lng = array();

        foreach( $locations as $location_row ) {

            $location_lat_lng = rp_get_lat_long_of_location( $location_row->location_id );

            if( !empty( $location_lat_lng ) ) {

                $distance = $maps_api->find_radius_distance( $input_lat_lng[0], $input_lat_lng[1], $location_lat_lng[0], $location_lat_lng[1] );

                $location_row->distance = $distance;

                $location_row->lat_lng = implode( ',', $location_lat_lng );

                $found_lat_lng[] = $location_row;

            } else {

                $location_row->distance = 'N/A';

                $location_row->lat_lng = '';

                $unfound_lat_lng[] = $location_row;

            }

        }

        if( !empty( $found_lat_lng ) ) {

            // convert found_lat_lng to array
            $found_lat_lng = json_decode( json_encode( $found_lat_lng ), true );

            // sort by smallest distance
            usort($found_lat_lng, function($a, $b) {

                return $a['distance'] <=> $b['distance'];

            });

            // convert back to object
            $found_lat_lng = json_decode( json_encode( $found_lat_lng ) );

        }
        
        $merged = array();

        // loop through all found lat lng
        foreach( $found_lat_lng as $found ) {

            $merged[] = $found;

        }

        // loop through all unfound lat lng
        foreach( $unfound_lat_lng as $unfound ) {

            $merged[] = $unfound;

        }

        return $merged;

    }

    return array();

}

function _rp_search_nearest_location( $input_address = '', $input_lat_lng = '' ) {

    $valid_lat_lng = true;

    if( !empty( $input_lat_lng ) ) {

        // replace double spaces with single space
        $input_lat_lng = preg_replace( '/\s+/', ' ', $input_lat_lng );

        $input_lat_lng = trim( $input_lat_lng );

        // make sure it only contains 0-9, ., comma, space or -
        if( !preg_match( '/^[0-9\.\,\s\-\+]+$/', $input_lat_lng ) ) {

            $valid_lat_lng = false;

        }

    }

    if( !empty( $input_lat_lng ) && $valid_lat_lng === true ) {
        
        // need to get formatted address from lat lng
        $formatted_address = rp_get_location_formatted_address( $input_lat_lng );

        $locations = rp_sort_locations_by_nearest_radius_distance( $input_lat_lng );

    } else if( !empty( $input_address ) && is_string( $input_address ) && strlen( trim( $input_address ) ) > 6 ) {

        // need to get lat lng from formatted address
        $formatted_address = $input_address;

        $input_lat_lng = rp_get_location_longitude_and_latitude( $formatted_address );

        $locations = rp_sort_locations_by_nearest_radius_distance( $input_lat_lng );

    } else {

        $formatted_address = '';

        $locations = rp_sort_locations_by_nearest_radius_distance( array() );

    }

    return array('locations' => $locations, 'formatted_address' => $formatted_address);

}

function rp_get_company_locations_count() {

    global $rpQuery;

    $rs_company_location = $rpQuery->prefix . "rs_company_location";

    $all_locations = $rpQuery->get_results("SELECT * FROM $rs_company_location;");

    if( !empty( $all_locations ) ) {

        return count( $all_locations );

    }

    return 0;

}

function rp_is_enabled_pricing_based_on_location() {

    static $last_el_enabled = null;

    if( $last_el_enabled !== null ) {

        return $last_el_enabled;

    }

    if( rp_get_company_locations_count() > 1 && rp_is_active_enhanced_locations_addon() == TRUE && rp_get_option('rp_el_pricing_based_on_location', '0') === '1' ) {

        $last_el_enabled = TRUE;
     
        return TRUE;

    }

    $last_el_enabled = FALSE;

    return FALSE;

}

function rp_is_enabled_dynamic_pricing_based_on_location() {
 
    if( rp_is_enabled_dynamic_pricing() == TRUE && rp_is_enabled_pricing_based_on_location() == TRUE ) {
     
        return TRUE;

    }

    return FALSE;

}

function rp_is_enabled_virtual_location() {

    return rp_is_active_enhanced_locations_addon();

}

function rp_is_enabled_location_selection_pdf() {

    $allow_location_selection = rp_get_option('rp_el_enable_location_selection_pdf', '1') == '1';

    return rp_is_active_enhanced_locations_addon() && $allow_location_selection;

}

function rp_is_enabled_ship_device_location() {

    $allow_location_selection = rp_get_option('rp_el_ship_device_choose_location', '1') == '1';

    return rp_is_active_enhanced_locations_addon() && $allow_location_selection;

}

function rp_get_nearest_location_for_customer( $customer_id_fk = 0 ) {

    if( empty( $customer_id_fk ) ) {

        return FALSE;

    }

    global $rpQuery;

    $rs_customer = $rpQuery->prefix . "rs_customer";

    // select * from rs_customer where customer_id = $customer_id_fk
    $customer = $rpQuery->get_row("SELECT * FROM `$rs_customer` WHERE `customer_id` = $customer_id_fk");

    if( !empty( $customer ) ) {

        $address = trim( $customer->customer_house_no . ' ' . $customer->customer_street_address . ' ' . $customer->customer_city . ' ' . $customer->customer_zipcode . ' ' . $customer->customer_country );

        return rp_get_nearest_location_for_delivery_methods( $address );

    }

    return FALSE;

}

function rp_can_use_google_maps_api_key() {

    if( rp_is_active_enhanced_locations_addon() == FALSE ) {

        return FALSE;

    }

    $rp_el_google_maps_api_key = rp_get_option('rp_el_google_maps_api_key', '');

    return !empty( trim( $rp_el_google_maps_api_key ?? '' ) );

}

function rp_get_maximum_radius_distance_formatted( $delivery_method = '' ) {

    global $wp_repair_lang;

    $maximum_radius_of_customer_location = rp_get_option('rp_'.$delivery_method.'_maximum_radius_of_customer_location', '');

    $maximum_radius_of_customer_location = (float) ($maximum_radius_of_customer_location ?? 0);

    if( $maximum_radius_of_customer_location < 0 ) {

        $maximum_radius_of_customer_location = 0;

    }

    $rp_el_prefered_distance_unit = rp_get_option('rp_el_prefered_distance_unit', 'km');

    $rp_el_prefered_distance_unit_text = $wp_repair_lang['nearest_location_distance_unit_'. $rp_el_prefered_distance_unit] ?? '';

    $rp_el_prefered_distance_unit_text_info = $rp_el_prefered_distance_unit_text;

    $rp_el_prefered_distance_unit_text_info = ucfirst($rp_el_prefered_distance_unit_text_info);

    if( trim($rp_el_prefered_distance_unit_text_info) == 'Km' ) {

        $rp_el_prefered_distance_unit_text_info = 'KM';

    }

    return number_format(round( $maximum_radius_of_customer_location, 2 )) . ' ' .$rp_el_prefered_distance_unit_text_info;

}

function rp_require_customer_address_maximum_distance_verification( $delivery_method = '' ) {

    if( rp_can_use_google_maps_api_key() == FALSE ) {

        return FALSE;

    }

    global $rpQuery;

    $rs_planning_and_discount = $rpQuery->prefix . "rs_planning_and_discount";

    $planning_discount = $rpQuery->get_results("SELECT * FROM $rs_planning_and_discount");

    $verify_customer_location_distance = rp_get_option('rp_'.$delivery_method.'_verify_customer_location_distance', '0');

    $maximum_radius_of_customer_location = rp_get_option('rp_'.$delivery_method.'_maximum_radius_of_customer_location', '');

    $maximum_radius_of_customer_location = (float) ($maximum_radius_of_customer_location ?? 0);

    if( $maximum_radius_of_customer_location < 0 ) {

        $maximum_radius_of_customer_location = 0;

    }
    
    return $verify_customer_location_distance == '1' && !empty( ($maximum_radius_of_customer_location ?? 0) ) && !empty( $planning_discount ) && ( ( $planning_discount[0]->{$delivery_method} ?? '' ) == '1');

}

function rp_verify_customer_address_details_before_finalize( $rp_pre_selected_location = 0 ) {

    $delivery_method = '';

    $_delivery_method_short = '';

    if(isset($_POST['d_method']) && strtolower($_POST['d_method']) === 'pickup service') {

        $_delivery_method_short = 'ps';

        $delivery_method = 'pickup_service';

    }

    if(isset($_POST['d_method']) && strtolower($_POST['d_method']) === 'repair on location') {

        $_delivery_method_short = 'rol';

        $delivery_method = 'repair_on_location';

    }

    if( empty( $delivery_method ) ) {

        return;

    }

    $house_no = $_POST[$_delivery_method_short.'_house_no'] ?? '';

    $street_address = $_POST[$_delivery_method_short.'_street_address'] ?? '';

    $user_city = $_POST[$_delivery_method_short.'_user_city'] ?? '';

    $user_zipcode = $_POST[$_delivery_method_short.'_user_zipcode'] ?? '';

    $user_country = $_POST[$_delivery_method_short.'_user_country'] ?? '';

    if( !rp_require_customer_address_maximum_distance_verification( $delivery_method ) ) {

        return;

    }

    $location_of_dm = 0;

    if( !empty( $rp_pre_selected_location ) ) {

        $location_of_dm = $rp_pre_selected_location;

    }

    $addressOfCustomer = trim( $house_no . ' ' . $street_address . ' ' . $user_city . ' ' . $user_zipcode . ' ' . $user_country );

    if( empty( $location_of_dm ) ) {

        if( $delivery_method == 'pickup_service') {

            $location_of_dm = rp_get_default_location_id_of_delivery_method('pickup_service');

        }

        if( $delivery_method == 'repair_on_location') {

            $location_of_dm = rp_get_default_location_id_of_delivery_method('repair_on_location');

        }

        if( $delivery_method == 'repair_on_location') {
      
            rp_add_filter_repair_on_your_location_locations();

        }

        if( $delivery_method == 'pickup_service') {

            rp_add_filter_pickup_service_locations();

        }

        $nearest_location_id = rp_get_nearest_location_for_delivery_methods( $addressOfCustomer );

        if( $delivery_method == 'repair_on_location') {

            rp_remove_filter_repair_on_your_location_locations();

        }

        if( $delivery_method == 'pickup_service') {

            rp_remove_filter_pickup_service_locations();

        }

        if( !empty( $nearest_location_id ) ) {

            $location_of_dm = $nearest_location_id;

        }

    }

    $search_results = _rp_search_nearest_location( $addressOfCustomer );

    $locations = $search_results['locations'];

    if( empty( $locations ) ) {

        echo json_encode(Array('status'=> false, 'rp_validation_error'  => 'No locations found'));

        exit;

    }

    $within_maximum = false;

    $maximum_radius_of_customer_location = rp_get_option('rp_'.$delivery_method.'_maximum_radius_of_customer_location', '');

    $maximum_radius_of_customer_location = (float) ($maximum_radius_of_customer_location ?? 0);

    foreach( $locations as $theLocation ) {

        if( $theLocation->location_id == $location_of_dm ) {

            if( !property_exists( $theLocation, 'distance' ) ) {

                echo json_encode(Array('status'=> false, 'rp_validation_error'  => 'Unable to find location distance. Looks like something is wrong with google maps api key.'));
    
                exit;
    
            }

            if( ( (float) $theLocation->distance ) <= $maximum_radius_of_customer_location ) {

                $within_maximum = true;

            }

        }

    }

    if( $within_maximum == true ) {

        return;

    } else {

        echo json_encode(Array('status'=> true, 'rp_validation_error'  => 'not-available'));

        exit;

    }

}

function rp_verify_customer_address_details() {

    global $rp_pre_selected_location;

    $rp_pre_selected_location = 0;

    if( rp_is_enabled_pricing_based_on_location() == TRUE ) {

        do_action('rp_before_getting_fe_pre_selected_location');
        
        $rp_pre_selected_location = intval( $_POST['rp_pre_selected_location'] ?? 0 );

        if( empty( $rp_pre_selected_location ) ) {

            return json_encode(Array('status' => false, 'message' => 'Invalid location id'));

        }

    }

    $required_vars = array('house_no', 'street_address', 'user_city', 'user_zipcode', 'delivery_method');

    foreach( $required_vars as $key ) {

        if( empty( $_POST[ $key ] ?? '' ) ) {

            echo json_encode(Array('status'=> false, 'message'  => $key . ' is required.'));

            exit;
            
        }

    }

    $house_no = $_POST['house_no'] ?? '';

    $street_address = $_POST['street_address'] ?? '';

    $user_city = $_POST['user_city'] ?? '';

    $user_zipcode = $_POST['user_zipcode'] ?? '';

    $user_country = $_POST['user_country'] ?? '';

    $delivery_method = $_POST['delivery_method'] ?? '';

    if( !rp_require_customer_address_maximum_distance_verification( $delivery_method ) ) {

        echo json_encode(Array('status'=> true, 'message'  => 'is-available'));

        exit;

    }

    $location_of_dm = 0;

    if( !empty( $rp_pre_selected_location ) ) {

        $location_of_dm = $rp_pre_selected_location;

    }

    $addressOfCustomer = trim( $house_no . ' ' . $street_address . ' ' . $user_city . ' ' . $user_zipcode . ' ' . $user_country );

    if( empty( $location_of_dm ) ) {

        if( $delivery_method == 'pickup_service') {

            $location_of_dm = rp_get_default_location_id_of_delivery_method('pickup_service');

        }

        if( $delivery_method == 'repair_on_location') {

            $location_of_dm = rp_get_default_location_id_of_delivery_method('repair_on_location');

        }

        if( $delivery_method == 'repair_on_location') {
      
            rp_add_filter_repair_on_your_location_locations();

        }

        if( $delivery_method == 'pickup_service') {

            rp_add_filter_pickup_service_locations();

        }

        $nearest_location_id = rp_get_nearest_location_for_delivery_methods( $addressOfCustomer );

        if( $delivery_method == 'repair_on_location') {

            rp_remove_filter_repair_on_your_location_locations();

        }

        if( $delivery_method == 'pickup_service') {

            rp_remove_filter_pickup_service_locations();

        }

        if( !empty( $nearest_location_id ) ) {

            $location_of_dm = $nearest_location_id;

        }

    }

    $search_results = _rp_search_nearest_location( $addressOfCustomer );

    $locations = $search_results['locations'];

    if( empty( $locations ) ) {

        echo json_encode(Array('status'=> false, 'message'  => 'No locations found'));

        exit;

    }

    $within_maximum = false;

    $maximum_radius_of_customer_location = rp_get_option('rp_'.$delivery_method.'_maximum_radius_of_customer_location', '');

    $maximum_radius_of_customer_location = (float) ($maximum_radius_of_customer_location ?? 0);

    foreach( $locations as $theLocation ) {

        if( $theLocation->location_id == $location_of_dm ) {

            if( !property_exists( $theLocation, 'distance' ) ) {

                echo json_encode(Array('status'=> false, 'message'  => 'Unable to find location distance. Looks like something is wrong with google maps api key.'));
    
                exit;
    
            }

            if( ( (float) $theLocation->distance ) <= $maximum_radius_of_customer_location ) {

                $within_maximum = true;

            }

        }

    }

    if( $within_maximum == true ) {

        echo json_encode(Array('status'=> true, 'message'  => 'is-available'));

        exit;

    } else {

        echo json_encode(Array('status'=> true, 'message'  => 'not-available'));

        exit;

    }

}

rp_ajax_for_public('rp_verify_customer_address_details', 'rp_verify_customer_address_details');

function rp_get_nearest_location_for_delivery_methods( $input_address = '' ) {

    $rp_el_google_maps_api_key = rp_get_option('rp_el_google_maps_api_key', '');

    $rp_el_auto_assign_location = rp_get_option('rp_el_auto_assign_location', '1');

    if( !empty( $rp_el_google_maps_api_key ) && $rp_el_auto_assign_location == '1' && rp_is_active_enhanced_locations_addon() === true ) {

        $search_results = _rp_search_nearest_location( $input_address );

        $locations = $search_results['locations'];

        if( !empty( $locations ) ) {

            $location = $locations[0];

            return $location->location_id;

        }

    }

    return FALSE;

}

function rp_do_not_exclude_virtual_location( $bool ) {

    return FALSE;

}

function rp_do_not_exclude_virtual_location_if_needed( $bool ) {

    global $rp_pre_selected_location;

    if( isset( $rp_pre_selected_location ) && !empty( $rp_pre_selected_location ) ) {

        return FALSE;

    }

    return $bool;

}

add_filter('rp_exclude_virtual_location', 'rp_do_not_exclude_virtual_location_if_needed', 9, 1);

function rp_el_location_pre_select_markup( $input_address = '', $input_lat_lng = '' ) {

    if( rp_is_active_enhanced_locations_addon() === false ) {

        return '';

    }

    $is_pdf_location_layout = false;

    add_filter('rp_exclude_virtual_location', 'rp_do_not_exclude_virtual_location', 10, 1);

    $search_results = _rp_search_nearest_location( $input_address, $input_lat_lng );

    remove_filter('rp_exclude_virtual_location', 'rp_do_not_exclude_virtual_location', 10 );

    $locations = $search_results['locations'];

    $formatted_address = $search_results['formatted_address'];

    $rp_el_google_maps_api_key = rp_get_option('rp_el_google_maps_api_key', '');

    $rp_enable_search_by_nearest_location = rp_get_option('rp_enable_search_by_nearest_location', '1');

    $rp_el_show_location_image_on_frontend = rp_get_option('rp_el_show_location_image_on_frontend', '1');

    $search_by_location = !empty( $rp_el_google_maps_api_key ) && $rp_enable_search_by_nearest_location == '1';

    $rp_el_show_location_image_on_frontend = $rp_el_show_location_image_on_frontend == '1';

    if( rp_is_active_enhanced_locations_addon() === false ) {

        $search_by_location = false;

        $rp_el_show_location_image_on_frontend = false;

    }

    include RP_EL_PLUGIN_PATH . 'html/el_location_pre_select_markup.php';

}

function rp_el_location_markup( $input_address = '', $input_lat_lng = '', $is_pdf_location_layout = false ) {

    $search_results = _rp_search_nearest_location( $input_address, $input_lat_lng );

    $locations = $search_results['locations'];

    $formatted_address = $search_results['formatted_address'];

    $rp_el_google_maps_api_key = rp_get_option('rp_el_google_maps_api_key', '');

    $rp_enable_search_by_nearest_location = rp_get_option('rp_enable_search_by_nearest_location', '1');

    $rp_el_show_location_image_on_frontend = rp_get_option('rp_el_show_location_image_on_frontend', '1');

    $search_by_location = !empty( $rp_el_google_maps_api_key ) && $rp_enable_search_by_nearest_location == '1';

    $rp_el_show_location_image_on_frontend = $rp_el_show_location_image_on_frontend == '1';

    if( rp_is_active_enhanced_locations_addon() === false ) {

        $search_by_location = false;

        $rp_el_show_location_image_on_frontend = false;

    }

    require RP_EL_PLUGIN_PATH . 'html/el_location_markup.php';

}

function rp_search_nearest_preselect_locations() {

    $rp_el_google_maps_api_key = rp_get_option('rp_el_google_maps_api_key', '');

    $rp_enable_search_by_nearest_location = rp_get_option('rp_enable_search_by_nearest_location', '1');

    if( empty( $rp_el_google_maps_api_key ) || $rp_enable_search_by_nearest_location != '1' ) {

        echo json_encode(Array('status'=> false, 'rp_validation_error'  => 'Something went wrong. Please try again later.'));

        exit;

    }

    rp_verify_enhanced_location_is_active();

    rp_verify_csrf_token_for_ajax('frontend');

    $input_address = trim( $_POST['address'] ?? '' );

    $input_lat_lng = trim( $_POST['lat_lng'] ?? '' );

    ob_start();

    rp_el_location_pre_select_markup( $input_address, $input_lat_lng );

    $html = ob_get_contents();

    ob_end_clean();

    echo json_encode(Array('status'=> true, 'html' => $html));

    exit;

}

function rp_search_nearest_locations() {

    $rp_el_google_maps_api_key = rp_get_option('rp_el_google_maps_api_key', '');

    $rp_enable_search_by_nearest_location = rp_get_option('rp_enable_search_by_nearest_location', '1');

    if( empty( $rp_el_google_maps_api_key ) || $rp_enable_search_by_nearest_location != '1' ) {

        echo json_encode(Array('status'=> false, 'rp_validation_error'  => 'Something went wrong. Please try again later.'));

        exit;

    }

    rp_verify_enhanced_location_is_active();

    rp_verify_csrf_token_for_ajax('frontend');

    $input_address = trim( $_POST['address'] ?? '' );

    $input_lat_lng = trim( $_POST['lat_lng'] ?? '' );

    $pdf_offer = trim( $_POST['pdf_offer'] ?? '0' );

    ob_start();

    $pdf_offer = $pdf_offer == '1' ? true : false;

    $delivery_method_id = '';

    if( isset( $_POST['delivery_method_id'] ) && !empty( $_POST['delivery_method_id'] ) ) {

        $delivery_method_id = trim( $_POST['delivery_method_id'] );

    }

    if( $delivery_method_id == 'come_by_our_store' ) {
        rp_add_filter_come_our_store_locations();
    }

    if( $delivery_method_id == 'ship_device' ) {
        rp_add_filter_ship_device_locations();
    }

    rp_el_location_markup( $input_address, $input_lat_lng, $pdf_offer );

    if( $delivery_method_id == 'come_by_our_store' ) {
        rp_remove_filter_come_our_store_locations();
    }

    if( $delivery_method_id == 'ship_device' ) {
        rp_remove_filter_ship_device_locations();
    }

    $html = ob_get_contents();

    ob_end_clean();

    echo json_encode(Array('status'=> true, 'html' => $html));

    exit;

}

function rp_get_place_autocomplete_suggestions() {

    $rp_el_google_maps_api_key = rp_get_option('rp_el_google_maps_api_key', '');

    $rp_enable_search_by_nearest_location = rp_get_option('rp_enable_search_by_nearest_location', '1');

    if( empty( $rp_el_google_maps_api_key ) || $rp_enable_search_by_nearest_location != '1' ) {

        echo json_encode(Array('status'=> false, 'rp_validation_error'  => 'Something went wrong. Please try again later.'));

        exit;

    }

    rp_verify_enhanced_location_is_active();

    rp_verify_csrf_token_for_ajax('frontend');

    $input_address = trim( $_POST['address'] ?? '' );

    $suggestions = rp_get_location_autocomplete_suggestions( $input_address );

    if( empty( $suggestions ) ) {

        $suggestions = array();

    }

    echo json_encode(Array('status'=> true, 'suggestions' => $suggestions));

    exit;

}

function rp_el_add_new_translation_by_release( $new_translation_groups = array() ) {

    $new_translation_groups['rp_el_plugin_translation_v_1p0'] = array(

        'please_select_any_delivery_method',

        'search_for_nearest_location',

        'approx_radius_distance',

        'browser_does_not_support_geolocation',

        'error_getting_geolocation',

        'address_is_too_short'

    );

    $new_translation_groups['rp_el_plugin_translation_v_1p1'] = array(

        'live_location_btn_text'

    );

    $new_translation_groups['rp_el_plugin_translation_v_1p2'] = array(

        'nearest_location_distance_unit_km',
        'nearest_location_distance_unit_miles'

    );

    return $new_translation_groups;

}

add_filter('rp_force_fetch_new_translation_groups', 'rp_el_add_new_translation_by_release', 12, 1);

function rp_get_default_repair_attr_row_by_id( $da_id = 0 ) {

    global $rpQuery;

    $rs_default_repair_attr = $rpQuery->prefix . "rs_default_repair_attr";

    $row = $rpQuery->get_row("SELECT * FROM `$rs_default_repair_attr` WHERE `da_id` = '".rp_escape_sql($da_id)."'");

    return $row;

}

function rp_get_individual_repair_attr_row_by_id( $a_id = 0 ) {

    global $rpQuery;

    $rs_repair_attr = $rpQuery->prefix . "rs_repair_attr";

    $row = $rpQuery->get_row("SELECT * FROM `$rs_repair_attr` WHERE `a_id` = '".rp_escape_sql($a_id)."'");

    return $row;

}

function rp_update_default_repair_attr_price_based_on_location( $da_id = 0, $location_id_fk = 0, $price = 0, $margin = FALSE, $is_free = 0 ) {

    global $rpQuery;

    $rs_location_prices = $rpQuery->prefix . 'rs_location_prices';

    $exists = $rpQuery->get_row("SELECT * FROM `$rs_location_prices` WHERE `type` = 'da' AND `connection_id` = '".rp_escape_sql($da_id)."' AND `location_id_fk` = '".rp_escape_sql($location_id_fk)."'");

    $the_da_uq_id = '';

    $the_dr_category = 0;

    if( !empty( $exists ) ) {

        $the_da_uq_id = $exists->uqid;

        $the_dr_category = $exists->dr_category;

        if( $margin === FALSE ) {

            // no need to update margin
            $margin_sql = '';

        } else {

            $margin_sql = ", `margin` = '".rp_escape_sql($margin)."'";

        }

        $rpQuery->query("UPDATE `$rs_location_prices` SET `price` = '".rp_escape_sql($price)."', `is_free` = '".rp_escape_sql($is_free)."' $margin_sql WHERE `type` = 'da' AND `connection_id` = '".rp_escape_sql($da_id)."' AND `location_id_fk` = '".rp_escape_sql($location_id_fk)."'");

    } else {

        if( $margin === FALSE ) {

            $margin = 0;

        }

        $da_row = rp_get_default_repair_attr_row_by_id( $da_id );
        
        $dr_category = 0;

        $da_uq_id = '';

        if( !empty( $da_row ) ) {

            $da_uq_id = $da_row->da_uq_id;

            $dr_row = rp_get_default_repair_row_by_id( $da_row->dr_id_fk );

            if( !empty( $dr_row ) ) {

                $dr_category = $dr_row->dr_category;

            }

        }

        $the_da_uq_id = $da_uq_id;

        $the_dr_category = $dr_category;

        $rpQuery->query("INSERT INTO `$rs_location_prices` (`type`, `connection_id`, `location_id_fk`, `price`, `margin`, `is_free`, `uqid`, `dr_category`) VALUES ('da', '".rp_escape_sql($da_id)."', '".rp_escape_sql($location_id_fk)."', '".rp_escape_sql($price)."', '".rp_escape_sql($margin)."', '".rp_escape_sql($is_free)."', '".rp_escape_sql($da_uq_id)."', '".rp_escape_sql($dr_category)."')");

    }

    // Remove duplicated rows
    $all = $rpQuery->get_results("SELECT * FROM `$rs_location_prices` WHERE `type` = 'da' AND `uqid` = '".rp_escape_sql($the_da_uq_id)."' AND `location_id_fk` = '".rp_escape_sql($location_id_fk)."' AND `dr_category` = '".rp_escape_sql($the_dr_category)."'");

    // if more than one, delete the one where connection id is not equal to da_id
    if( count( $all ) > 1 ) {

        foreach( $all as $the_row ) {

            if( $the_row->connection_id != $da_id ) {

                $rpQuery->query("DELETE FROM `$rs_location_prices` WHERE `type` = 'da' AND `id` = '".rp_escape_sql($the_row->id)."'");

            }

        }

    }

}

function rp_update_individual_repair_attr_price_only_based_on_loc( $a_id = 0, $location_id_fk = 0, $price = 0 ) {

    global $rpQuery;

    $rs_location_prices = $rpQuery->prefix . 'rs_location_prices';

    $exists = $rpQuery->get_row("SELECT * FROM `$rs_location_prices` WHERE `type` = 'a' AND `connection_id` = '".rp_escape_sql($a_id)."' AND `location_id_fk` = '".rp_escape_sql($location_id_fk)."'");

    $a_row = rp_get_individual_repair_attr_row_by_id( $a_id );

    $dr_category = 0;

    $a_uq_id = '';

    $r_uq_id = '';

    $r_row = NULL;

    if( !empty( $a_row ) ) {

        $a_uq_id = $a_row->a_uq_id;

        $r_row = rp_get_individual_repair_row_by_id( $a_row->r_id_fk );

        if( !empty( $r_row ) ) {

            $dr_category = rp_get_model_cached_category_by_mid( $r_row->m_id_fk );

            $r_uq_id = $r_row->r_uq_id;

        }

    }

    if( !empty( $exists ) ) {

        $rpQuery->query("UPDATE `$rs_location_prices` SET `price` = '".rp_escape_sql($price)."' WHERE `type` = 'a' AND `connection_id` = '".rp_escape_sql($a_id)."' AND `location_id_fk` = '".rp_escape_sql($location_id_fk)."'");

    } else {

        $da_row = rp_get_default_repair_attr_row_by_uq_id( $a_uq_id, $dr_category );

        $margin = 0;

        $is_free = 0;

        if( !empty( $da_row ) ) {

            $da_row = apply_filters('rp_overwrite_default_repair_attr_row', $da_row, $location_id_fk);

            $margin = $da_row->da_margin ?? 0;

        }

        $rpQuery->query("INSERT INTO `$rs_location_prices` (`type`, `connection_id`, `location_id_fk`, `price`, `margin`, `is_free`, `uqid`, `dr_category`) VALUES ('a', '".rp_escape_sql($a_id)."', '".rp_escape_sql($location_id_fk)."', '".rp_escape_sql($price)."', '".rp_escape_sql($margin)."', '".rp_escape_sql($is_free)."', '".rp_escape_sql($a_uq_id)."', '".rp_escape_sql($dr_category)."')");

    }

}

function rp_update_individual_repair_attr_price_based_on_location( $a_id = 0, $location_id_fk = 0, $price = 0, $margin = FALSE, $is_free = 0 ) {

    global $rpQuery;

    $rs_location_prices = $rpQuery->prefix . 'rs_location_prices';

    $exists = $rpQuery->get_row("SELECT * FROM `$rs_location_prices` WHERE `type` = 'a' AND `connection_id` = '".rp_escape_sql($a_id)."' AND `location_id_fk` = '".rp_escape_sql($location_id_fk)."'");

    $a_row = rp_get_individual_repair_attr_row_by_id( $a_id );
        
    $dr_category = 0;

    $a_uq_id = '';

    $r_uq_id = '';

    $r_row = NULL;

    if( !empty( $a_row ) ) {

        $a_uq_id = $a_row->a_uq_id;

        $r_row = rp_get_individual_repair_row_by_id( $a_row->r_id_fk );

        if( !empty( $r_row ) ) {

            $dr_category = rp_get_model_cached_category_by_mid( $r_row->m_id_fk );

            $r_uq_id = $r_row->r_uq_id;

        }

    }

    if( !empty( $exists ) ) {

        if( $margin === FALSE ) {

            // no need to update margin
            $margin_sql = '';

        } else {

            $margin_sql = ", `margin` = '".rp_escape_sql($margin)."'";

        }

        $rpQuery->query("UPDATE `$rs_location_prices` SET `price` = '".rp_escape_sql($price)."', `is_free` = '".rp_escape_sql($is_free)."' $margin_sql WHERE `type` = 'a' AND `connection_id` = '".rp_escape_sql($a_id)."' AND `location_id_fk` = '".rp_escape_sql($location_id_fk)."'");

    } else {

        if( $margin === FALSE ) {

            $margin = 0;

        }

        $rpQuery->query("INSERT INTO `$rs_location_prices` (`type`, `connection_id`, `location_id_fk`, `price`, `margin`, `is_free`, `uqid`, `dr_category`) VALUES ('a', '".rp_escape_sql($a_id)."', '".rp_escape_sql($location_id_fk)."', '".rp_escape_sql($price)."', '".rp_escape_sql($margin)."', '".rp_escape_sql($is_free)."', '".rp_escape_sql($a_uq_id)."', '".rp_escape_sql($dr_category)."')");

    }

    if( !empty( $a_uq_id ) && !empty( $r_row ) && !empty( $dr_category ) ) {

        $is_default = in_array($r_uq_id, rp_get_all_dr_uq_id_from_rs_default_repair_table());

        $fully_unchanged = rp_is_fully_unchanged_default_repair_individually( $r_row->r_id, $r_row->m_id_fk );

        if( $is_default == TRUE && $fully_unchanged == TRUE ) {

            rp_delete_individual_repairs_attr_price_if_matches_exactly( $a_id, $a_uq_id, $location_id_fk, $dr_category );

        }

    }

}

function rp_get_default_repair_row_by_id( $dr_id = 0 ) {

    global $rpQuery;

    $rs_default_repair = $rpQuery->prefix . "rs_default_repair";

    $row = $rpQuery->get_row("SELECT * FROM `$rs_default_repair` WHERE `dr_id` = '".rp_escape_sql($dr_id)."'");

    return $row;

}

function rp_get_individual_repair_row_by_id( $r_id = 0 ) {

    global $rpQuery;

    $rs_repair = $rpQuery->prefix . "rs_repair";

    $row = $rpQuery->get_row("SELECT * FROM `$rs_repair` WHERE `r_id` = '".rp_escape_sql($r_id)."'");

    return $row;

}

function rp_update_default_repair_price_based_on_location( $dr_id = 0, $location_id_fk = 0, $price = 0, $margin = FALSE, $is_free = 0 ) {

    global $rpQuery;

    $rs_location_prices = $rpQuery->prefix . 'rs_location_prices';

    $exists = $rpQuery->get_row("SELECT * FROM `$rs_location_prices` WHERE `type` = 'dr' AND `connection_id` = '".rp_escape_sql($dr_id)."' AND `location_id_fk` = '".rp_escape_sql($location_id_fk)."'");

    $the_dr_uq_id = '';

    $the_dr_category = 0;

    if( !empty( $exists ) ) {

        $the_dr_uq_id = $exists->uqid;

        $the_dr_category = $exists->dr_category;

        if( $margin === FALSE ) {

            // no need to update margin
            $margin_sql = '';

        } else {

            $margin_sql = ", `margin` = '".rp_escape_sql($margin)."'";

        }

        $rpQuery->query("UPDATE `$rs_location_prices` SET `price` = '".rp_escape_sql($price)."', `is_free` = '".rp_escape_sql($is_free)."' $margin_sql WHERE `type` = 'dr' AND `connection_id` = '".rp_escape_sql($dr_id)."' AND `location_id_fk` = '".rp_escape_sql($location_id_fk)."'");

    } else {

        if( $margin === FALSE ) {

            $margin = 0;

        }

        $dr_row = rp_get_default_repair_row_by_id( $dr_id );
        
        $dr_category = 0;

        $dr_uq_id = '';

        if( !empty( $dr_row ) ) {

            $dr_category = $dr_row->dr_category;

            $dr_uq_id = $dr_row->dr_uq_id;

        }

        $the_dr_uq_id = $dr_uq_id;

        $the_dr_category = $dr_category;

        $rpQuery->query("INSERT INTO `$rs_location_prices` (`type`, `connection_id`, `location_id_fk`, `price`, `margin`, `is_free`, `uqid`, `dr_category`) VALUES ('dr', '".rp_escape_sql($dr_id)."', '".rp_escape_sql($location_id_fk)."', '".rp_escape_sql($price)."', '".rp_escape_sql($margin)."', '".rp_escape_sql($is_free)."', '".rp_escape_sql($dr_uq_id)."', '".rp_escape_sql($dr_category)."')");

    }

    // Remove duplicated rows
    $all = $rpQuery->get_results("SELECT * FROM `$rs_location_prices` WHERE `type` = 'dr' AND `uqid` = '".rp_escape_sql($the_dr_uq_id)."' AND `location_id_fk` = '".rp_escape_sql($location_id_fk)."' AND `dr_category` = '".rp_escape_sql($the_dr_category)."'");

    // if more than one, delete the one where connection id is not equal to dr_id
    if( count( $all ) > 1 ) {

        foreach( $all as $the_row ) {

            if( $the_row->connection_id != $dr_id ) {

                $rpQuery->query("DELETE FROM `$rs_location_prices` WHERE `type` = 'dr' AND `id` = '".rp_escape_sql($the_row->id)."'");

            }

        }

    }

}

function rp_update_individual_repair_price_only_based_on_loc( $r_id = 0, $location_id_fk = 0, $price = 0 ) {

    global $rpQuery;

    $rs_location_prices = $rpQuery->prefix . 'rs_location_prices';

    $exists = $rpQuery->get_row("SELECT * FROM `$rs_location_prices` WHERE `type` = 'r' AND `connection_id` = '".rp_escape_sql($r_id)."' AND `location_id_fk` = '".rp_escape_sql($location_id_fk)."'");

    $r_row = rp_get_individual_repair_row_by_id( $r_id );

    $dr_category = 0;

    $r_uq_id = '';

    if( !empty( $r_row ) ) {

        $dr_category = rp_get_model_cached_category_by_mid( $r_row->m_id_fk );

        $r_uq_id = $r_row->r_uq_id;

    }

    if( !empty( $exists ) ) {

        $rpQuery->query("UPDATE `$rs_location_prices` SET `price` = '".rp_escape_sql($price)."' WHERE `type` = 'r' AND `connection_id` = '".rp_escape_sql($r_id)."' AND `location_id_fk` = '".rp_escape_sql($location_id_fk)."'");

    } else {

        $dr_row = rp_get_default_repair_row_by_uq_id( $r_uq_id, $dr_category );

        $margin = 0;

        $is_free = 0;
        
        if( !empty( $dr_row ) ) {

            $dr_row = apply_filters('rp_overwrite_default_repair_row', $dr_row, $location_id_fk);

            $margin = $dr_row->dr_margin ?? 0;

        }

        $rpQuery->query("INSERT INTO `$rs_location_prices` (`type`, `connection_id`, `location_id_fk`, `price`, `margin`, `is_free`, `uqid`, `dr_category`) VALUES ('r', '".rp_escape_sql($r_id)."', '".rp_escape_sql($location_id_fk)."', '".rp_escape_sql($price)."', '".rp_escape_sql($margin)."', '".rp_escape_sql($is_free)."', '".rp_escape_sql($r_uq_id)."', '".rp_escape_sql($dr_category)."')");

    }

}

function rp_update_individual_repair_price_based_on_location( $r_id = 0, $location_id_fk = 0, $price = 0, $margin = FALSE, $is_free = 0 ) {

    global $rpQuery;

    $rs_location_prices = $rpQuery->prefix . 'rs_location_prices';

    $exists = $rpQuery->get_row("SELECT * FROM `$rs_location_prices` WHERE `type` = 'r' AND `connection_id` = '".rp_escape_sql($r_id)."' AND `location_id_fk` = '".rp_escape_sql($location_id_fk)."'");

    $r_row = rp_get_individual_repair_row_by_id( $r_id );

    $dr_category = 0;

    $r_uq_id = '';

    if( !empty( $r_row ) ) {

        $dr_category = rp_get_model_cached_category_by_mid( $r_row->m_id_fk );

        $r_uq_id = $r_row->r_uq_id;

    }

    if( !empty( $exists ) ) {

        if( $margin === FALSE ) {

            // no need to update margin
            $margin_sql = '';

        } else {

            $margin_sql = ", `margin` = '".rp_escape_sql($margin)."'";

        }

        $rpQuery->query("UPDATE `$rs_location_prices` SET `price` = '".rp_escape_sql($price)."', `is_free` = '".rp_escape_sql($is_free)."' $margin_sql WHERE `type` = 'r' AND `connection_id` = '".rp_escape_sql($r_id)."' AND `location_id_fk` = '".rp_escape_sql($location_id_fk)."'");

    } else {

        if( $margin === FALSE ) {

            $margin = 0;

        }

        $rpQuery->query("INSERT INTO `$rs_location_prices` (`type`, `connection_id`, `location_id_fk`, `price`, `margin`, `is_free`, `uqid`, `dr_category`) VALUES ('r', '".rp_escape_sql($r_id)."', '".rp_escape_sql($location_id_fk)."', '".rp_escape_sql($price)."', '".rp_escape_sql($margin)."', '".rp_escape_sql($is_free)."', '".rp_escape_sql($r_uq_id)."', '".rp_escape_sql($dr_category)."')");

    }

    if( !empty( $r_uq_id ) && !empty( $dr_category ) ) {

        $is_default = in_array($r_uq_id, rp_get_all_dr_uq_id_from_rs_default_repair_table());

        $fully_unchanged = rp_is_fully_unchanged_default_repair_individually( $r_row->r_id, $r_row->m_id_fk );

        if( $is_default == TRUE && $fully_unchanged == TRUE ) {

            rp_delete_individual_repairs_price_if_matches_default_exactly( $r_row->r_id, $r_uq_id, $location_id_fk, $dr_category );

        }

    }

}

function rp_delete_individual_repairs_attr_price_if_matches_exactly( $a_id = 0, $a_uq_id = '', $location_id_fk = 0, $dr_category = 0 ) {

    global $rpQuery;

    $rs_location_prices = $rpQuery->prefix . 'rs_location_prices';

    // get where type = 'da' and uqid = $a_uq_id and location_id_fk = $location_id_fk and dr_category = $dr_category
    $default_row = $rpQuery->get_row("SELECT * FROM `$rs_location_prices` WHERE `type` = 'da' AND `uqid` = '".rp_escape_sql($a_uq_id)."' AND `location_id_fk` = '".rp_escape_sql($location_id_fk)."' AND `dr_category` = '".rp_escape_sql($dr_category)."'");

    if( !empty( $default_row ) ) {

        // delete individual prices where it matches exactly the default

        $price = $default_row->price;

        $margin = $default_row->margin;

        $is_free = $default_row->is_free;

        // delete where type = 'a' and uqid = $a_uq_id and location_id_fk = $location_id_fk and dr_category = $dr_category and price = $price and margin = $margin and is_free = $is_free and connection_id = $a_id
        $rpQuery->query("DELETE FROM `$rs_location_prices` WHERE `type` = 'a' AND `uqid` = '".rp_escape_sql($a_uq_id)."' AND `location_id_fk` = '".rp_escape_sql($location_id_fk)."' AND `dr_category` = '".rp_escape_sql($dr_category)."' AND `price` = '".rp_escape_sql($price)."' AND `margin` = '".rp_escape_sql($margin)."' AND `is_free` = '".rp_escape_sql($is_free)."' AND `connection_id` = '".rp_escape_sql($a_id)."'");

    }

}

function rp_delete_individual_repairs_price_if_matches_default_exactly( $r_id = 0, $r_uq_id = '', $location_id_fk = 0, $dr_category = 0 ) {

    global $rpQuery;

    $rs_location_prices = $rpQuery->prefix . 'rs_location_prices';

    // get where type = 'dr' and uqid = $r_uq_id and location_id_fk = $location_id_fk and dr_category = $dr_category
    $default_row = $rpQuery->get_row("SELECT * FROM `$rs_location_prices` WHERE `type` = 'dr' AND `uqid` = '".rp_escape_sql($r_uq_id)."' AND `location_id_fk` = '".rp_escape_sql($location_id_fk)."' AND `dr_category` = '".rp_escape_sql($dr_category)."'");

    if( !empty( $default_row ) ) {

        // delete individual prices where it matches exactly the default

        $price = $default_row->price;

        $margin = $default_row->margin;

        $is_free = $default_row->is_free;

        // delete where type = 'r' and uqid = $r_uq_id and location_id_fk = $location_id_fk and dr_category = $dr_category and price = $price and margin = $margin and is_free = $is_free and connection_id = $r_id
        $rpQuery->query("DELETE FROM `$rs_location_prices` WHERE `type` = 'r' AND `uqid` = '".rp_escape_sql($r_uq_id)."' AND `location_id_fk` = '".rp_escape_sql($location_id_fk)."' AND `dr_category` = '".rp_escape_sql($dr_category)."' AND `price` = '".rp_escape_sql($price)."' AND `margin` = '".rp_escape_sql($margin)."' AND `is_free` = '".rp_escape_sql($is_free)."' AND `connection_id` = '".rp_escape_sql($r_id)."'");

    }

}

function rp_get_repair_price_based_on_location_and_connection( $type = '', $connection_id = 0, $location_id = 0 ) {

    if( empty( $type ) || empty( $connection_id ) || empty( $location_id ) ) {

        return 0;

    }

    global $rpQuery;

    $rs_location_prices = $rpQuery->prefix . 'rs_location_prices';

    $sql = "SELECT * FROM `$rs_location_prices` WHERE `type` = '".rp_escape_sql( $type )."' AND `connection_id` = '".rp_escape_sql( $connection_id )."' AND `location_id_fk` = '".rp_escape_sql( $location_id )."' LIMIT 1;";

    $row = $rpQuery->get_row( $sql );

    if( !empty( $row ) ) {

        return array( $row->price, $row->margin, $row->is_free );

    }

    return array(0, 0, 0);

}

function _rp_overwrite_default_repair_based_on_location( $row = null, $selected_location = 0 ) {
    
    if( !empty( $row ) ) {

        list( $price, $margin, $is_free ) = rp_get_repair_price_based_on_location_and_connection( 'dr', $row->dr_id, $selected_location );

        $row->dr_price = $price;

        $row->dr_margin = $margin;

        $row->is_free = $is_free;

    }

    return $row;

}

function rp_overwrite_default_repair_based_on_location( $row = null, $selected_location = 0 ) {

    if( rp_is_enabled_pricing_based_on_location() == TRUE ) {

        $row = _rp_overwrite_default_repair_based_on_location( $row, $selected_location );

    }

    return $row;

}

add_filter('rp_overwrite_default_repair_row', 'rp_overwrite_default_repair_based_on_location', 10, 2);

function _rp_overwrite_default_repair_attr_based_on_location( $row = null, $selected_location = 0 ) {

    if( !empty( $row ) ) {

        list( $price, $margin, $is_free ) = rp_get_repair_price_based_on_location_and_connection( 'da', $row->da_id, $selected_location );

        $row->da_price = $price;

        $row->da_margin = $margin;

    }

    return $row;

}

function rp_overwrite_default_repair_attr_based_on_location( $row = null, $selected_location = 0 ) {

    if( rp_is_enabled_pricing_based_on_location() == TRUE ) {

        $row = _rp_overwrite_default_repair_attr_based_on_location( $row, $selected_location );

    }

    return $row;

}

add_filter('rp_overwrite_default_repair_attr_row', 'rp_overwrite_default_repair_attr_based_on_location', 10, 2);

function rp_get_main_repair_price_based_on_location_or_default( $connection_id = 0, $uqid = '', $location_id_fk = 0 ) {

    global $rpQuery;

    $rs_location_prices = $rpQuery->prefix . 'rs_location_prices';

    // check if connection_id exists in rs_location_prices
    $row = $rpQuery->get_row("SELECT * FROM `$rs_location_prices` WHERE `type` = 'r' AND `connection_id` = '".rp_escape_sql($connection_id)."' AND `location_id_fk` = '".rp_escape_sql($location_id_fk)."'");

    if( !empty( $row ) ) {

        return array( $row->price, $row->margin, $row->is_free );

    }

    // try to check if default repair price exists (uqid) and type = dr
    $row = $rpQuery->get_row("SELECT * FROM `$rs_location_prices` WHERE `type` = 'dr' AND `uqid` = '".rp_escape_sql($uqid)."' AND `location_id_fk` = '".rp_escape_sql($location_id_fk)."'");

    if( !empty( $row ) ) {

        return array( $row->price, $row->margin, $row->is_free );

    }

    return array(0, 0, 0);

}

function _rp_overwrite_individual_repair_based_on_location( $row = null, $selected_location = 0 ) {
    
    if( !empty( $row ) ) {

        list( $price, $margin, $is_free ) = rp_get_main_repair_price_based_on_location_or_default( $row->r_id, $row->r_uq_id, $selected_location );

        $row->r_price = $price;

        $row->r_margin = $margin;

        $row->is_free = $is_free;

    }

    return $row;

}

function rp_overwrite_individual_repair_based_on_location( $row = null, $selected_location = 0 ) {

    if( rp_is_enabled_pricing_based_on_location() == TRUE ) {

        $row = _rp_overwrite_individual_repair_based_on_location( $row, $selected_location );

    }

    return $row;

}

add_filter('rp_overwrite_individual_repair_row', 'rp_overwrite_individual_repair_based_on_location', 10, 2);

function rp_get_main_repair_attr_price_based_on_location_or_default( $connection_id = 0, $uqid = '', $location_id_fk = 0 ) {

    global $rpQuery;

    $rs_location_prices = $rpQuery->prefix . 'rs_location_prices';

    // check if connection_id exists in rs_location_prices
    $row = $rpQuery->get_row("SELECT * FROM `$rs_location_prices` WHERE `type` = 'a' AND `connection_id` = '".rp_escape_sql($connection_id)."' AND `location_id_fk` = '".rp_escape_sql($location_id_fk)."'");

    if( !empty( $row ) ) {

        return array( $row->price, $row->margin, $row->is_free );

    }

    // try to check if default repair price exists (uqid) and type = da
    $row = $rpQuery->get_row("SELECT * FROM `$rs_location_prices` WHERE `type` = 'da' AND `uqid` = '".rp_escape_sql($uqid)."' AND `location_id_fk` = '".rp_escape_sql($location_id_fk)."'");

    if( !empty( $row ) ) {

        return array( $row->price, $row->margin, $row->is_free );

    }

    return array(0, 0, 0);

}

function _rp_overwrite_individual_repair_attr_based_on_location( $row = null, $selected_location = 0 ) {
    
    if( !empty( $row ) ) {

        list( $price, $margin, $is_free ) = rp_get_main_repair_attr_price_based_on_location_or_default( $row->a_id, $row->a_uq_id, $selected_location );

        $row->a_price = $price;

        $row->a_margin = $margin;

    }

    return $row;

}

function rp_overwrite_individual_repair_attr_based_on_location( $row = null, $selected_location = 0 ) {

    if( rp_is_enabled_pricing_based_on_location() == TRUE ) {

        $row = _rp_overwrite_individual_repair_attr_based_on_location( $row, $selected_location );

    }

    return $row;

}

add_filter('rp_overwrite_individual_repair_attr_row', 'rp_overwrite_individual_repair_attr_based_on_location', 10, 2);


function rp_filter_schedules_that_loc_head_can_manage( $schedule_groups = array() ) {

    if( rp_current_user_has_full_access_cached() ) {

        return $schedule_groups;

    }

    global $rpQuery;

    $rs_company_location = $rpQuery->prefix . 'rs_company_location';

    $allowed_locations = rp_get_allowed_locations_of_current_user();

    $filtered = array();

    foreach( $schedule_groups as $group ) {

        if( ($group->related_to ?? 0) != 0 && in_array( $group->related_to, $allowed_locations ) ) {

            $filtered[] = $group;

            continue;

        }

        // get all where location_id in $allowed_locations and schedule_group_id = $group->id

        $rows = $rpQuery->get_row("SELECT * FROM `$rs_company_location` WHERE `location_id` IN (".implode(',', $allowed_locations).") AND `schedule_group_id` = '".rp_escape_sql($group->id)."'");

        if( empty( $rows ) ) {

            continue;

        }

        $filtered[] = $group;

    }

    return $filtered;

}

function rp_filter_schedules_that_loc_head_can_manage_only_custom( $schedule_groups = array() ) {

    if( rp_current_user_has_full_access_cached() ) {

        return $schedule_groups;

    }

    global $rpQuery;

    $rs_company_location = $rpQuery->prefix . 'rs_company_location';

    $allowed_locations = rp_get_allowed_locations_of_current_user();

    $filtered = array();

    foreach( $schedule_groups as $group ) {

        if( ($group->related_to ?? 0) != 0 && in_array( $group->related_to, $allowed_locations ) ) {

            $filtered[] = $group;

        }

    }

    return $filtered;

}

function rp_get_ids_of_all_schedule_groups() {

    static $ids = NULL;

    if( $ids !== NULL ) {

        return $ids;

    }

    global $rpQuery;

    $rs_schedule_groups = $rpQuery->prefix . 'rs_schedule_groups';

    $rows = $rpQuery->get_results("SELECT `id` FROM `$rs_schedule_groups`");

    $ids = array();

    foreach( $rows as $row ) {

        $ids[] = (int) $row->id;

    }

    return $ids;

}

function rp_convert_to_individual_schedule() {

    rp_verify_enhanced_location_is_active();

    rp_verify_csrf_token_for_ajax('enhanced_locations');

    global $rpQuery;

    $rs_schedule_groups = $rpQuery->prefix . 'rs_schedule_groups';

    $rs_schedule_group_timing = $rpQuery->prefix . 'rs_schedule_group_timing';

    $rs_special_timing = $rpQuery->prefix . 'rs_special_timing';

    $rs_company_location = $rpQuery->prefix . 'rs_company_location';

    $schedule_group_id = (int) ($_POST['id'] ?? 0);

    // This request is not expected for full access users

    if( empty( $schedule_group_id ) || rp_current_user_has_full_access_cached() ) {

        echo json_encode(Array('status'=> false, 'rp_validation_error'  => 'Invalid request'));

        exit;

    }

    rp_verify_editing_schedule_group();

    // make sure schedule group exists
    $schedule_group = $rpQuery->get_row("SELECT * FROM `$rs_schedule_groups` WHERE `id` = '".rp_escape_sql($schedule_group_id)."'");

    if( empty( $schedule_group ) ) {

        echo json_encode(Array('status'=> false, 'rp_validation_error'  => 'Schedule group not found'));

        exit;

    }

    $schedule_group_timings = $rpQuery->get_results("SELECT * FROM `$rs_schedule_group_timing` WHERE `schedule_group_id` = '".rp_escape_sql($schedule_group_id)."'");

    // all rs_special_timing
    $all_special_timings = $rpQuery->get_results("SELECT * FROM `$rs_special_timing`");

    $all_company_locations = rp_get_all_company_locations();

    $allowed_locations = rp_get_allowed_locations_of_current_user();

    $filtered_locations = array();

    $filtered_locations_names = array();

    foreach( $all_company_locations as $theLocation ) {

        if( $theLocation->schedule_group_id == $schedule_group_id && in_array( $theLocation->location_id, $allowed_locations ) ) {

            $filtered_locations[] = $theLocation->location_id;

            $filtered_locations_names[] = $theLocation->location_name;
            
        }

    }

    if( !empty( $filtered_locations ) ) {

        foreach( $filtered_locations as $theKey => $loc_id ) {

            // check if schedule already exists where related_to = $loc_id
            $exists = $rpQuery->get_row("SELECT * FROM `$rs_schedule_groups` WHERE `related_to` = '".rp_escape_sql($loc_id)."'"); 

            if( !empty( $exists ) ) {

                // delete
                $rpQuery->query("DELETE FROM `$rs_schedule_groups` WHERE `related_to` = '".rp_escape_sql($loc_id)."'");

                // delete from rs_schedule_group_timing where schedule_group_id = $exists->id
                $rpQuery->query("DELETE FROM `$rs_schedule_group_timing` WHERE `schedule_group_id` = '".rp_escape_sql($exists->id)."'");

            }

            // insert new schedule group
            $rpQuery->query("INSERT INTO `$rs_schedule_groups` (`name`, `date_time`, `related_to`) VALUES ('".rp_escape_sql($filtered_locations_names[$theKey] . ' > Individual Schedule')."', '".rp_escape_sql($schedule_group->date_time)."', '".rp_escape_sql($loc_id)."')");

            $new_schedule_group_id = $rpQuery->insert_id;

            // now apply this new schedule group to this location in loop
            $rpQuery->query("UPDATE `$rs_company_location` SET `schedule_group_id` = '".rp_escape_sql($new_schedule_group_id)."' WHERE `location_id` = '".rp_escape_sql($loc_id)."' AND `schedule_group_id` = '".rp_escape_sql($schedule_group_id)."'");

            // now create duplicate of timings
            if( !empty( $schedule_group_timings ) ) {

                foreach( $schedule_group_timings as $theTiming ) {

                    $rpQuery->query("INSERT INTO `$rs_schedule_group_timing` (`cs_day`, `cs_open_timing`, `cs_close_timing`, `cs_breaktime_from`, `cs_breaktime_to`, `is_closed`, `schedule_group_id`, `date_time`) VALUES ('".rp_escape_sql($theTiming->cs_day)."', '".rp_escape_sql($theTiming->cs_open_timing)."', '".rp_escape_sql($theTiming->cs_close_timing)."', '".rp_escape_sql($theTiming->cs_breaktime_from)."', '".rp_escape_sql($theTiming->cs_breaktime_to)."', '".rp_escape_sql($theTiming->is_closed)."', '".rp_escape_sql($new_schedule_group_id)."', '".rp_escape_sql($theTiming->date_time)."')");

                }

            }

            // update special timing
            foreach( $all_special_timings as $theSpecialTiming ) {

                $location_id_fks = explode(',', ($theSpecialTiming->location_id_fk ?? ''));

                $filtered_loc_ids = array();

                $has_schedule_group_id = FALSE;

                foreach( $location_id_fks as $loc_fk ) {

                    if( empty( $loc_fk ) || empty( trim( $loc_fk ) ) ) {

                        continue;

                    }

                    if( strpos( trim( $loc_fk ) , 'sg_' ) !== FALSE ) {

                        $sg_id = (int) str_replace('sg_', '', trim( $loc_fk ));

                        if( !in_array( $sg_id, rp_get_ids_of_all_schedule_groups() ) ) {

                            continue;

                        }

                        if( $sg_id == $schedule_group_id ) {

                            $has_schedule_group_id = TRUE;

                        }

                        $filtered_loc_ids[] = $loc_fk;

                    } else {

                        $filtered_loc_ids[] = $loc_fk;

                    }

                }

                if( $has_schedule_group_id == TRUE ) {

                    $filtered_loc_ids[] = 'sg_' . $new_schedule_group_id;

                    // update
                    $rpQuery->query("UPDATE `$rs_special_timing` SET `location_id_fk` = '".(implode(',', $filtered_loc_ids))."' WHERE `cs_id` = '".rp_escape_sql($theSpecialTiming->cs_id)."'");

                }

            }

        }

    }
 
    echo json_encode(Array('status'=> true, 'message' => 'Schedule group has been converted to individual schedule'));

    exit;

}

rp_ajax_for_admin('rp_convert_to_individual_schedule', 'rp_convert_to_individual_schedule');

function rp_save_location_order() {

    rp_verify_enhanced_location_is_active();

    rp_verify_csrf_token_for_ajax('enhanced_locations');

    rp_verify_user_full_access_ajax();

    $actual_total_count = rp_get_total_company_locations();

    $location_ids = $_POST['location_ids'] ?? array();

    if( !is_array( $location_ids ) ) {

        $location_ids = array();

    }

    $main_location_id = rp_get_main_location_id_of_company();

    $all_actual_locations = rp_get_all_company_locations();

    $valid_location_ids = array();

    foreach( $all_actual_locations as $theLocation ) {

        $valid_location_ids[] = (int) $theLocation->location_id;

    }

    // make sure actual_total_count is equal to count of location_ids
    if( count( $location_ids ) != $actual_total_count ) {

        echo json_encode(Array('status'=> false, 'rp_validation_error'  => 'Not all locations are included in posted data'));

        exit;

    }

    // make sure all location_ids are within valid locations
    foreach( $location_ids as $loc_id ) {

        $loc_id = (int) $loc_id;

        if( !in_array( $loc_id, $valid_location_ids ) ) {

            echo json_encode(Array('status'=> false, 'rp_validation_error'  => 'Invalid location id #' . $loc_id));

            exit;

        }

    }

    // make sure main location is on top
    if( $location_ids[0] != $main_location_id ) {

        echo json_encode(Array('status'=> false, 'rp_validation_error'  => 'Main location should be on top'));

        exit;

    }

    global $rpQuery;

    $rs_company_location = $rpQuery->prefix . 'rs_company_location';

    $order = 0;

    foreach( $location_ids as $loc_id ) {

        $loc_id = (int) $loc_id;

        $rpQuery->query("UPDATE `$rs_company_location` SET `location_order` = '".rp_escape_sql($order)."' WHERE `location_id` = '".rp_escape_sql($loc_id)."'");

        $order++;

    }

    // success message
    echo json_encode(Array('status'=> true, 'message' => 'Location order has been saved'));

    exit;

}

rp_ajax_for_admin('rp_save_location_order', 'rp_save_location_order');

F1le Man4ger