<?php

if (!function_exists('propertybase_settings_tabs')) {
    function propertybase_settings_tabs($tab = null): array
    {
        $settingTabs = [
            "general" => [
                "slug" => "general",
                "name" => _l('propertybase_general_settings'),
                "view" => module_views_path(PROPERTYBASE_MODULE_NAME, 'admin/settings/includes/general.php'),
                "position" => 5,
                "icon" => "fa fa-cog",
                "href" => "#",
                "update_url" => admin_url(PROPERTYBASE_MODULE_NAME . '/settings'),
                "badge" => [],
                "children" => [],
            ],
            "property_categories" => [
                "slug" => "property_categories",
                "name" => _l('propertybase_property_categories'),
                "view" => module_views_path(PROPERTYBASE_MODULE_NAME, 'admin/settings/includes/property_categories.php'),
                "table_path" => module_views_path(PROPERTYBASE_MODULE_NAME, 'admin/settings/tables/property_categories.php'),
                "table_class" => 'property-categories',
                "position" => 10,
                "icon" => "fas fa-list-alt",
                "href" => "#",
                "badge" => [],
                "children" => [],
            ],
            "property_amenities_types" => [
                "slug" => "property_amenities_types",
                "name" => _l('propertybase_property_amenities_types'),
                "view" => module_views_path(PROPERTYBASE_MODULE_NAME, 'admin/settings/includes/property_amenities_types.php'),
                "table_path" => module_views_path(PROPERTYBASE_MODULE_NAME, 'admin/settings/tables/property_amenities_types.php'),
                "table_class" => 'property-amenities-types',
                "position" => 10,
                "icon" => "fas fa-tags",
                "href" => "#",
                "badge" => [],
                "children" => [],
            ],
            "property_amenities" => [
                "slug" => "property_amenities",
                "name" => _l('propertybase_property_amenities'),
                "view" => module_views_path(PROPERTYBASE_MODULE_NAME, 'admin/settings/includes/property_amenities.php'),
                "table_path" => module_views_path(PROPERTYBASE_MODULE_NAME, 'admin/settings/tables/property_amenities.php'),
                "table_class" => 'property-amenities',
                "position" => 10,
                "icon" => "fas fa-couch",
                "href" => "#",
                "badge" => [],
                "children" => [],
            ],
            "property_area_types" => [
                "slug" => "property_area_types",
                "name" => _l('propertybase_property_area_types'),
                "view" => module_views_path(PROPERTYBASE_MODULE_NAME, 'admin/settings/includes/property_area_types.php'),
                "table_path" => module_views_path(PROPERTYBASE_MODULE_NAME, 'admin/settings/tables/property_area_types.php'),
                "table_class" => 'property-area-type',
                "position" => 10,
                "icon" => "fas fa-ruler-combined",
                "href" => "#",
                "badge" => [],
                "children" => [],
            ],
            "property_ownership_types" => [
                "slug" => "property_ownership_types",
                "name" => _l('propertybase_property_ownership_types'),
                "view" => module_views_path(PROPERTYBASE_MODULE_NAME, 'admin/settings/includes/property_ownership_types.php'),
                "table_path" => module_views_path(PROPERTYBASE_MODULE_NAME, 'admin/settings/tables/property_ownership_types.php'),
                "table_class" => 'property-ownership-types',
                "position" => 10,
                "icon" => "fas fa-user-shield",
                "href" => "#",
                "badge" => [],
                "children" => [],
            ],
            "energy_efficiency_types" => [
                "slug" => "energy_efficiency_types",
                "name" => _l('propertybase_property_energy_efficiency_types'),
                "view" => module_views_path(PROPERTYBASE_MODULE_NAME, 'admin/settings/includes/energy_efficiency_types.php'),
                "table_path" => module_views_path(PROPERTYBASE_MODULE_NAME, 'admin/settings/tables/property_energy_efficiency_types.php'),
                "table_class" => 'property-energy-efficiency-types',
                "position" => 10,
                "icon" => "fas fa-bolt",
                "href" => "#",
                "badge" => [],
                "children" => [],
            ]
        ];

        $settingTabs = hooks()->apply_filters('propertybase_get_settings_tabs', $settingTabs);

        if ($tab !== null && isset($settingTabs[$tab])) {
            return $settingTabs[$tab];
        }

        return $settingTabs;
    }
}

if (!function_exists('propertybase_load_view')) {
    function propertybase_load_view(string $file_path, array $data = [])
    {
        $hook_data = hooks()->apply_filters('propertybase_load_view', [
            'file_path' => $file_path,
            'data' => $data
        ]);

        $file_path = $hook_data['file_path'] ?? $file_path;
        $data = $hook_data['data'] ?? $data;

        if (file_exists($file_path)) {

            if (!empty($data)) {
                extract($data, EXTR_SKIP);
            }

            ob_start();
            try {
                include($file_path);
            } catch (Exception $e) {
                log_message('error', 'Error including view file: ' . $e->getMessage());
                echo "An error occurred while loading the view.";
            }
            ob_end_flush();
        } else {
            log_message('error', 'View file not found: ' . $file_path);
            echo "View file not found: " . htmlspecialchars($file_path, ENT_QUOTES, 'UTF-8');
        }
    }
}

if (!function_exists('propertybase_property_purposes')) {
    /**
     * Retrieve property purposes or a specific purpose based on ID.
     *
     * @param int|null $id Optional ID to retrieve a specific purpose.
     * @return array|string|null Returns the full purposes array, a specific purpose string, or null if ID not found.
     */
    function propertybase_property_purposes($id = null, $returnTranslated = false)
    {
        $purposes = [
            [
                'id' => 1,
                'purpose' => $returnTranslated ? _l('propertybase_sale') : 'propertybase_sale'
            ],
            [
                'id' => 2,
                'purpose' => $returnTranslated ? _l('propertybase_rent') : 'propertybase_rent'
            ],
            [
                'id' => 3,
                'purpose' => $returnTranslated ? _l('propertybase_rent_and_sale') : 'propertybase_rent_and_sale'
            ],
        ];
        $purposes = hooks()->apply_filters('propertybase_get_property_purposes', $purposes);

        if ($id !== null) {
            foreach ($purposes as $purpose) {
                if ($purpose['id'] == $id) {
                    return $purpose['purpose'];
                }
            }
            return null;
        }

        return $purposes;
    }
}

if (!function_exists('propertybase_get_property_price')) {
    function propertybase_get_property_price($property_id, $html = false, $formatted = false)
    {
        $CI = &get_instance();
        $CI->load->model('propertybase_model');

        $property = $CI->propertybase_model->get($property_id);

        if (!$property) {
            return null;
        }

        $property_purpose = $property->property_purpose;
        $sale_price = $property->sale_price;
        $rent_price_incl = $property->rent_price_incl;
        $rent_price_excl = $property->rent_price_excl;

        $result = null;

        if ($property_purpose == 1) {
            $result = $formatted ? app_format_money($sale_price, get_base_currency()) : $sale_price;
        } elseif ($property_purpose == 2) {
            $rent_price = !empty($rent_price_excl) ? $rent_price_excl : $rent_price_incl;
            $rent_type = !empty($rent_price_excl) ? ' (Excl.)' : ' (Incl.)';
            $result = $formatted
                ? app_format_money($rent_price, get_base_currency()) . $rent_type
                : $rent_price . $rent_type;
        } elseif ($property_purpose == 3) {
            $rent_price = !empty($rent_price_excl) ? $rent_price_excl : $rent_price_incl;
            $rent_type = !empty($rent_price_excl) ? ' (Excl.)' : ' (Incl.)';

            if ($html) {
                $sale = $formatted ? app_format_money($sale_price, get_base_currency()) : $sale_price;
                $rent = $formatted
                    ? app_format_money($rent_price, get_base_currency()) . $rent_type
                    : $rent_price . $rent_type;
                $result = "Sale Price: $sale, Rent Price: $rent";
            } else {
                $result = [
                    'sale_price' => $formatted ? app_format_money($sale_price, get_base_currency()) : $sale_price,
                    'rent_price' => $formatted
                        ? app_format_money($rent_price, get_base_currency()) . $rent_type
                        : $rent_price . $rent_type,
                ];
            }
        }

        return hooks()->apply_filters('propertybase_get_property_price', $result, $property);
    }
}


if (!function_exists('propertybase_property_amenities_types')) {
    function propertybase_property_amenities_types($type_id = null)
    {
        $CI = &get_instance();
        $CI->load->model('propertybase/PropertyAmenitiesTypes_model');

        if (!is_null($type_id)) {
            return $CI->PropertyAmenitiesTypes_model->get($type_id);
        }

        return $CI->PropertyAmenitiesTypes_model->get_all();
    }
}

if (!function_exists('propertybase_handle_property_main_image')) {
    function propertybase_handle_property_main_image($asset_id)
    {
        $path = PROPERTYBASE_PROPERTY_MAIN_IMAGE_PATH . $asset_id . '/';
        $CI = &get_instance();

        if (isset($_FILES['file']['name'])) {
            hooks()->do_action('before_upload_property_main_image', $asset_id);
            $tmpFilePath = $_FILES['file']['tmp_name'];

            if (!empty($tmpFilePath) && $tmpFilePath != '') {
                _maybe_create_upload_path($path);
                $filename = $_FILES['file']['name'];
                $newFilePath = $path . $filename;
                if (move_uploaded_file($tmpFilePath, $newFilePath)) {
                    $attachment = [];
                    $attachment[] = [
                        'file_name' => $filename,
                        'filetype' => $_FILES['file']['type'],
                    ];

                    $CI->misc_model->add_attachment_to_database($asset_id, 'property_main_image', $attachment);
                }
            }
        }
    }
}

if (!function_exists('propertybase_handle_property_floor_image')) {
    function propertybase_handle_property_floor_image($asset_id)
    {
        $path = PROPERTYBASE_PROPERTY_FLOOR_IMAGE_PATH . $asset_id . '/';
        $CI = &get_instance();

        if (isset($_FILES['floor']['name'])) {
            hooks()->do_action('before_upload_property_floor_image', $asset_id);
            $tmpFilePath = $_FILES['floor']['tmp_name'];

            if (!empty($tmpFilePath) && $tmpFilePath != '') {
                _maybe_create_upload_path($path);
                $filename = $_FILES['floor']['name'];
                $newFilePath = $path . $filename;
                if (move_uploaded_file($tmpFilePath, $newFilePath)) {
                    $attachment = [];
                    $attachment[] = [
                        'file_name' => $filename,
                        'filetype' => $_FILES['floor']['type'],
                    ];

                    $CI->misc_model->add_attachment_to_database($asset_id, 'property_floor_image', $attachment);
                }
            }
        }
    }
}

if (!function_exists('handle_property_attachments_upload')) {
    function handle_property_attachments_upload($id, $customer_upload = false)
    {
        $path = PROPERTYBASE_PROPERTY_ATTACHMENTS_PATH . $id . '/';
        $CI = &get_instance();
        $totalUploaded = 0;

        if (isset($_FILES['file']['name'])
            && ($_FILES['file']['name'] != '' || is_array($_FILES['file']['name']) && count($_FILES['file']['name']) > 0)) {
            if (!is_array($_FILES['file']['name'])) {
                $_FILES['file']['name'] = [$_FILES['file']['name']];
                $_FILES['file']['type'] = [$_FILES['file']['type']];
                $_FILES['file']['tmp_name'] = [$_FILES['file']['tmp_name']];
                $_FILES['file']['error'] = [$_FILES['file']['error']];
                $_FILES['file']['size'] = [$_FILES['file']['size']];
            }

            _file_attachments_index_fix('file');
            for ($i = 0; $i < count($_FILES['file']['name']); $i++) {
                hooks()->do_action('before_upload_property_attachment', $id);
                // Get the temp file path
                $tmpFilePath = $_FILES['file']['tmp_name'][$i];
                // Make sure we have a filepath
                if (!empty($tmpFilePath) && $tmpFilePath != '') {
                    if (_perfex_upload_error($_FILES['file']['error'][$i])
                        || !_upload_extension_allowed($_FILES['file']['name'][$i])) {
                        continue;
                    }

                    _maybe_create_upload_path($path);
                    $filename = unique_filename($path, $_FILES['file']['name'][$i]);
                    $newFilePath = $path . $filename;
                    // Upload the file into the temp dir
                    if (move_uploaded_file($tmpFilePath, $newFilePath)) {
                        $attachment = [];
                        $attachment[] = [
                            'file_name' => $filename,
                            'filetype' => $_FILES['file']['type'][$i],
                        ];

                        if (is_image($newFilePath)) {
                            create_img_thumb($newFilePath, $filename);
                        }

                        if ($customer_upload == true) {
                            $attachment[0]['staffid'] = 0;
                            $attachment[0]['contact_id'] = get_contact_user_id();
                            $attachment['visible_to_customer'] = 1;
                        }

                        $CI->misc_model->add_attachment_to_database($id, 'property_attachment', $attachment);
                        $totalUploaded++;
                    }
                }
            }
        }

        return (bool)$totalUploaded;
    }
}

if (!function_exists('get_all_property_attachments')) {
    function get_all_property_attachments($id)
    {
        $CI = &get_instance();

        $attachments = [];

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

        $attachments[] = $asset_attachments;

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

if (!function_exists('propertybase_customer_has_properties')) {
    function propertybase_customer_has_properties(int $customer_id)
    {
        $totalCustomerProjects = total_rows(db_prefix() . 'propertybase_properties', ['rel_id' => get_instance()->db->escape_str($customer_id), 'rel_type' => 'customer']);

        return ($totalCustomerProjects > 0 ? true : false);
    }
}

if (!function_exists('propertybase_get_property_name_by_id')) {
    function propertybase_get_property_name_by_id(int $id)
    {
        $CI = &get_instance();
        $property = $CI->app_object_cache->get('property-name-data-' . $id);

        if (!$property) {
            $CI->db->select('name');
            $CI->db->where('id', $id);
            $property = $CI->db->get(db_prefix() . 'propertybase_properties')->row();
            $CI->app_object_cache->add('property-name-data-' . $id, $property);
        }

        if ($property) {
            return $property->name;
        }

        return '';
    }
}

if (!function_exists('propertybase_formatted_property_name')) {
    function propertybase_formatted_property_name(int $property_id, $asLink = false)
    {
        $CI = &get_instance();
        $CI->load->model(PROPERTYBASE_MODULE_NAME . '/propertybase_model');

        $data = $CI->propertybase_model->get($property_id);

        $format = '';

        if (!is_null($data)) {
            $format = '#' . $data->id . ' - ' . $data->name;
        }

        if ($asLink) {
            $format = '<a target="_blank" href="' . admin_url(PROPERTYBASE_MODULE_NAME . '/view/' . $property_id) . '">' . $format . '</a>';
        }

        return hooks()->apply_filters('propertybase_formatted_property_name', $format, [
            'property_id' => $property_id,
            'property_data' => $data
        ]);
    }
}

if (!function_exists('propertybase_formatted_property_location')) {
    function propertybase_formatted_property_location(int $property_id)
    {
        $CI = &get_instance();
        $CI->load->model(PROPERTYBASE_MODULE_NAME . '/propertybase_model');

        $data = $CI->propertybase_model->get($property_id);

        $propertyLocation = '';
        if (!empty($data->address)) {
            $propertyLocation .= $data->address . ' ';
        }
        if (!empty($data->city)) {
            $propertyLocation .= $data->city . ' ';
        }

        if (!empty($data->country) && $data->country !== 0) {
            $propertyLocation .= get_country_name($data->country);
        }

        return hooks()->apply_filters('propertybase_formatted_property_location', $propertyLocation, [
            'property_id' => $property_id,
            'property_data' => $data
        ]);
    }
}

if (!function_exists('propertybase_load_invoices_total_template')) {
    function propertybase_load_invoices_total_template()
    {
        $CI = &get_instance();

        $CI->load->model(PROPERTYBASE_MODULE_NAME . '/propertybase_model');
        $CI->load->model('invoices_model');

        $_data = $CI->input->post();

        if (!$CI->input->post('customer_id')) {
            $multiple_currencies = call_user_func('is_using_multiple_currencies');
        } else {
            $_data['customer_id'] = $CI->input->post('customer_id');
            $multiple_currencies = call_user_func('is_client_using_multiple_currencies', $CI->input->post('customer_id'));
        }

        if ($CI->input->post('property_id')) {
            $_data['property_id'] = $CI->input->post('property_id');
        }

        if ($multiple_currencies) {
            $CI->load->model('currencies_model');
            $data['invoices_total_currencies'] = $CI->currencies_model->get();
        }

        $data['invoices_years'] = $CI->invoices_model->get_invoices_years();

        if (
            count($data['invoices_years']) >= 1
            && !\app\services\utilities\Arr::inMultidimensional($data['invoices_years'], 'year', date('Y'))
        ) {
            array_unshift($data['invoices_years'], ['year' => date('Y')]);
        }

        $data['total_result'] = $CI->propertybase_model->get_invoices_total($_data);
        $data['_currency'] = $data['total_result']['currencyid'];

        propertybase_load_view(module_views_path(PROPERTYBASE_MODULE_NAME, 'admin/properties/templates/property_invoices_total_template.php'), $data);
    }
}

if (!function_exists('propertybase_list_landing_page_themes')) {
    function propertybase_list_landing_page_themes(): array
    {
        $themesList = [
            [
                'id' => 'default',
                'title' => 'Default Theme',
                'thumbnail' => substr(module_dir_url(PROPERTYBASE_MODULE_NAME . '/uploads/theme_thumbnails/default_theme.png'), 0, -1),
                'theme_index_path' => module_views_path(PROPERTYBASE_MODULE_NAME, '/landing_page/template/default/index.php'),
                'theme_property_path' => module_views_path(PROPERTYBASE_MODULE_NAME, '/landing_page/template/default/property-detail.php'),
            ]
        ];

        return hooks()->apply_filters('propertybase_list_landing_page_themes', $themesList);
    }
}

if (!function_exists('propertybase_get_landing_page_details')) {
    /**
     * Get landing page details by ID with a filter to allow modifications.
     *
     * @param string $id The ID of the landing page theme.
     * @return array|null The landing page details or null if not found.
     */
    function propertybase_get_landing_page_details(string $id): ?array
    {
        $themes = propertybase_list_landing_page_themes();

        $theme = array_filter($themes, function ($theme) use ($id) {
            return $theme['id'] === $id;
        });

        if (empty($theme)) {
            return null;
        }

        $themeDetails = reset($theme);

        return hooks()->apply_filters('propertybase_get_landing_page_details', $themeDetails, $id);
    }
}

if (!function_exists('propertybase_get_property_main_image')) {
    /**
     * Get the main image for a property
     *
     * @param int $property_id
     */
    function propertybase_get_property_main_image($property_id)
    {
        $CI = &get_instance();
        $CI->load->model('propertybase_model');

        $imageData = $CI->propertybase_model->get_property_main_image_attachment($property_id);

        return hooks()->apply_filters('propertybase_get_property_main_image', $imageData, $property_id);
    }
}

if (!function_exists('propertybase_load_module_assets')) {
    function propertybase_load_module_images(string $path)
    {
        return substr(module_dir_url($path), 0, -1);
    }
}

if (!function_exists('propertybase_fetch_properties')) {
    /**
     * Fetch properties based on conditions with extensibility via hooks
     *
     * @param array $conditions Conditions for querying properties
     * @return array List of properties with main image and extensibility hooks
     */
    function propertybase_fetch_properties($conditions = [])
    {
        $CI = &get_instance();
        $CI->load->model('propertybase_model');

        $CI->db->where($conditions);
        $properties = $CI->db->get(db_prefix() . 'propertybase_properties')->result_array();

        foreach ($properties as &$property) {
            $property['main_image'] = propertybase_get_property_main_image($property['id']) ?: [];

            $property = hooks()->apply_filters('propertybase_fetch_property', $property);
        }

        return hooks()->apply_filters('propertybase_fetch_properties', $properties, $conditions);
    }
}

if (!function_exists('propertybase_get_property_category_name')) {
    /**
     * Retrieve the category name based on the category ID.
     *
     * @param int $category_id The ID of the category.
     * @return string|null The category name or null if the category is not found.
     */
    function propertybase_get_property_category_name($category_id)
    {
        $CI = &get_instance();
        $CI->load->model('propertycategories_model');

        $category = $CI->propertycategories_model->get($category_id);
        $category_name = $category ? $category->name : null;

        return hooks()->apply_filters('propertybase_get_property_category_name', $category_name, $category_id);
    }
}

if (!function_exists('propertybase_get_property_ownership_name')) {
    /**
     * Retrieve the ownership type name based on the ownership type ID.
     *
     * @param int $ownership_type_id The ID of the ownership type.
     * @return string|null The ownership type name or null if not found.
     */
    function propertybase_get_property_ownership_name($ownership_type_id)
    {
        $CI = &get_instance();
        $CI->load->model('PropertyOwnershipTypes_model');

        $ownership_type = $CI->PropertyOwnershipTypes_model->get($ownership_type_id);
        $ownership_name = $ownership_type ? $ownership_type->name : null;

        return hooks()->apply_filters('propertybase_get_property_ownership_name', $ownership_name, $ownership_type_id);
    }
}

if (!function_exists('propertybase_get_property_single_page_url')) {
    /**
     * Get Property Landing Page Single Page URL
     *
     * @param string $id The ID of the property.
     * @return string|null The landing page details or null if not found.
     */
    function propertybase_get_property_single_page_url(string $id): ?string
    {
        $url = site_url(PROPERTYBASE_MODULE_NAME . '/Landingpage/property/' . $id);

        return hooks()->apply_filters('propertybase_get_property_single_page_url', $url, $id);
    }
}

if (!function_exists('propertybase_yes_no_text')) {
    function propertybase_yes_no_text($value)
    {
        if ($value == 1) {
            return ucfirst(_l('yes'));
        }

        return ucfirst(_l('no'));
    }
}

if (!function_exists('propertybase_yes_no_options')) {
    function propertybase_yes_no_options()
    {
        return [
            [
                "id" => "1",
                'value' => ucfirst(_l('yes'))
            ],
            [
                "id" => "2",
                'value' => ucfirst(_l('no'))
            ]
        ];
    }
}

if (!function_exists('propertybase_property_statuses')) {
    function propertybase_property_statuses()
    {
        $availableStatuses = [
            [
                'id' => 1,
                'value' => 'available',
                'name' => _l('propertybase_property_status_available'),
                'badge' => '<span class="label property-status-available">' . _l('propertybase_property_status_available') . '</span>',
                'icon' => 'fa fa-check-circle'
            ],
            [
                'id' => 2,
                'value' => 'allocate',
                'name' => _l('propertybase_property_status_allocate'),
                'badge' => '<span class="label property-status-allocate">' . _l('propertybase_property_status_allocate_badge') . '</span>',
                'icon' => 'fa fa-handshake'
            ],
            [
                'id' => 3,
                'value' => 'revocate',
                'name' => _l('propertybase_property_status_revocate'),
                'badge' => '<span class="label property-status-revocate">' . _l('propertybase_property_status_revocate') . '</span>',
                'icon' => 'fa fa-undo'
            ],
            [
                'id' => 4,
                'value' => 'sell',
                'name' => _l('propertybase_property_status_sell'),
                'badge' => '<span class="label property-status-sell">' . _l('propertybase_property_status_sell_badge') . '</span>',
                'icon' => 'fa fa-dollar-sign'
            ]
        ];

        return hooks()->apply_filters('propertybase_available_property_statuses', $availableStatuses);
    }
}

if (!function_exists('propertybase_get_status_data')) {
    function propertybase_get_status_data($identifier)
    {
        $statuses = propertybase_property_statuses();

        foreach ($statuses as $status) {
            if ($status['id'] == $identifier || $status['value'] == $identifier) {
                return $status;
            }
        }

        return null;
    }
}

if (!function_exists('propertybase_allocate_to_options')) {
    function propertybase_allocate_to_options()
    {
        $allocateToOptions = [
            [
                'value' => 'customer',
                'name' => _l('propertybase_allocate_to_customer')
            ],
            [
                'value' => 'project',
                'name' => _l('propertybase_allocate_to_project')
            ]
        ];

        return hooks()->apply_filters('propertybase_allocate_to_options', $allocateToOptions);
    }
}

if (!function_exists('propertybase_signature_pad_js')) {
    function propertybase_signature_pad_js()
    {
        hooks()->do_action('propertybase_before_signature_pad_js');

        $signatureCode = '
        SignaturePad.prototype.toDataURLAndRemoveBlanks = function() {
     var canvas = this._ctx.canvas;
       // First duplicate the canvas to not alter the original
       var croppedCanvas = document.createElement("canvas"),
       croppedCtx = croppedCanvas.getContext("2d");

       croppedCanvas.width = canvas.width;
       croppedCanvas.height = canvas.height;
       croppedCtx.drawImage(canvas, 0, 0);

       // Next do the actual cropping
       var w = croppedCanvas.width,
       h = croppedCanvas.height,
       pix = {
         x: [],
         y: []
       },
       imageData = croppedCtx.getImageData(0, 0, croppedCanvas.width, croppedCanvas.height),
       x, y, index;

       for (y = 0; y < h; y++) {
         for (x = 0; x < w; x++) {
           index = (y * w + x) * 4;
           if (imageData.data[index + 3] > 0) {
             pix.x.push(x);
             pix.y.push(y);

           }
         }
       }
       pix.x.sort(function(a, b) {
         return a - b
       });
       pix.y.sort(function(a, b) {
         return a - b
       });
       var n = pix.x.length - 1;

       w = pix.x[n] - pix.x[0];
       h = pix.y[n] - pix.y[0];
       var cut = croppedCtx.getImageData(pix.x[0], pix.y[0], w, h);

       croppedCanvas.width = w;
       croppedCanvas.height = h;
       croppedCtx.putImageData(cut, 0, 0);

       return croppedCanvas.toDataURL();
     };


     function signaturePadChanged() {

       var input = document.getElementById("signatureInput");
       var $signatureLabel = $("#signatureLabel");
       $signatureLabel.removeClass("text-danger");

       if (signaturePad.isEmpty()) {
           $signatureLabel.addClass("text-danger");
           input.value = "";
           return false;
       }

       $("#signatureInput-error").remove();
       var partBase64 = signaturePad.toDataURLAndRemoveBlanks();
       partBase64 = partBase64.split(",")[1];
       input.value = partBase64;
     }

        var canvas = document.getElementById("signature");
        var clearButton = wrapper.querySelector("[data-action=clear]");
        var undoButton = wrapper.querySelector("[data-action=undo]");
        var identityFormSubmit = document.getElementById("identityConfirmationForm");

        var signaturePad = new SignaturePad(canvas, {
        maxWidth: 2,
      onEnd:function(){
            signaturePadChanged();
        }
    });

     clearButton.addEventListener("click", function(event) {
         signaturePad.clear();
         signaturePadChanged();
     });

     undoButton.addEventListener("click", function(event) {
         var data = signaturePad.toData();
         if (data) {
             data.pop(); // remove the last dot or line
             signaturePad.fromData(data);
             signaturePadChanged();
         }
     });

        $(document).on("submit", "#identityConfirmationForm", function () {
            signaturePadChanged();
        });
        ';

        $signatureCode = hooks()->apply_filters('propertybase_signature_pad_js', $signatureCode);
        hooks()->do_action('propertybase_after_signature_pad_js');

        return $signatureCode;
    }
}

if (!function_exists('propertybase_get_property_assigned_data')) {
    function propertybase_get_property_assigned_data($assigned_data)
    {
        if (empty($assigned_data)) {
            return '';
        }

        $assignedTo = '';
        $link = '';
        $name = '';

        if ($assigned_data->assigned_to === 'staff') {
            $assignedTo = _l('staff');
            $link = admin_url('staff/member/' . $assigned_data->assigned_id);
            $name = get_staff_full_name($assigned_data->assigned_id);
        }
        if ($assigned_data->assigned_to === 'customers') {
            $assignedTo = ucfirst(_l('customer'));
            $link = admin_url('clients/client/' . $assigned_data->assigned_id);
            $name = get_client($assigned_data->assigned_id)->company;
        }
        if ($assigned_data->assigned_to === 'project') {
            $assignedTo = _l('project');
            $link = admin_url('projects/view/' . $assigned_data->assigned_id);
            $name = get_project($assigned_data->assigned_id)->name;
        }

        return $assignedTo . ' - <a target="_blank" href="' . $link . '">' . $name . '</a>';
    }
}

if (!function_exists('propertybase_return_lead_form_submit_location')) {
    function propertybase_return_lead_form_submit_location($property_id)
    {
        $url = site_url(PROPERTYBASE_MODULE_NAME . '/Landingpage/submit_lead/' . $property_id);

        return hooks()->apply_filters('propertybase_return_lead_form_submit_location', $url, $property_id);
    }
}

if (!function_exists('propertybase_render_lead_form')) {
    function propertybase_render_lead_form($property_data)
    {
        $CI =& get_instance();
        $CI->load->library('session');
        $csrf_name = $CI->security->get_csrf_token_name();
        $csrf_hash = $CI->security->get_csrf_hash();

        $success_message = $CI->session->flashdata('success');
        $error_message = $CI->session->flashdata('error');

        $html = '';

        // Display success or error messages
        if ($success_message) {
            $color = "green";
            $html .= '
        <p style="color: '.$color.'">' . $success_message . '</p>
        ';
        }

        if ($error_message) {
            $color = "red";
            $html .= '
        <p style="color: '.$color.'">' . $error_message . '</p>
        ';
        }

        if (get_option('propertybase_display_agent_profile')) {
            $profileStyle = "height: 50px;width: 50px";
            $html .= '
            <div class="media">
        <div class="media-left">
            <a href="#">
                <img class="media-object" style="'.$profileStyle.'" src="' . staff_profile_image_url($property_data->selected_agent) . '" alt="img">
            </a>
        </div>
        <div class="media-body">
            <h4 class="media-heading"><a href="#">' . get_staff_full_name($property_data->selected_agent) . '</a></h4>
            <p>Responsible agent for this property</p>
        </div>
    </div>
            ';
        }

        $html .= '
    <form action="' . propertybase_return_lead_form_submit_location($property_data->id) . '" method="POST">
        <input type="hidden" name="' . $csrf_name . '" value="' . $csrf_hash . '">
        <div class="aa-single-advance-search">
            <input type="text" name="name" placeholder="Full name" required>
        </div>
        <div class="aa-single-advance-search">
            <input type="text" name="email" placeholder="Email">
        </div>
        <div class="aa-single-advance-search">
            <input type="text" name="phonenumber" placeholder="Phone" required>
        </div>
        <div class="aa-single-advance-search">
            <textarea id="description" name="description" placeholder="Your Message" class="form-control" rows="4" required></textarea>
        </div>
        <div class="checkbox checkbox-primary no-mtop checkbox-inline">
            <input type="checkbox" id="consent" name="consent" required>
            <label for="consent">I consent to have this site collect my Name, Email, and Phone</label>
        </div>
        <div class="aa-single-advance-search">
            <input type="submit" value="Send Message" class="aa-search-btn">
        </div>
    </form>
';

        return hooks()->apply_filters('propertybase_render_lead_form', $html, $property_data);
    }
}

if (!function_exists('propertybase_handle_maintenance_request_attachments')) {
    function propertybase_handle_maintenance_request_attachments($requestId, $index_name = 'attachments')
    {
        $path = PROPERTYBASE_PROPERTY_MAINTENANCE_REQUESTS_PATH . $requestId . '/';
        $uploaded_files = [];

        if (isset($_FILES[$index_name])) {
            _file_attachments_index_fix($index_name);

            for ($i = 0; $i < count($_FILES[$index_name]['name']); $i++) {
                if ($i <= 5) {
                    // Get the temp file path
                    $tmpFilePath = $_FILES[$index_name]['tmp_name'][$i];
                    // Make sure we have a filepath
                    if (!empty($tmpFilePath) && $tmpFilePath != '') {
                        // Getting file extension
                        $extension = strtolower(pathinfo($_FILES[$index_name]['name'][$i], PATHINFO_EXTENSION));

                        $allowed_extensions = explode(',', get_option('ticket_attachments_file_extensions'));
                        $allowed_extensions = array_map('trim', $allowed_extensions);
                        // Check for all cases if this extension is allowed
                        if (!in_array('.' . $extension, $allowed_extensions)) {
                            continue;
                        }
                        _maybe_create_upload_path($path);
                        $filename = unique_filename($path, $_FILES[$index_name]['name'][$i]);
                        $newFilePath = $path . $filename;
                        // Upload the file into the temp dir
                        if (move_uploaded_file($tmpFilePath, $newFilePath)) {
                            array_push($uploaded_files, [
                                'file_name' => $filename,
                                'filetype' => $_FILES[$index_name]['type'][$i],
                            ]);
                        }
                    }
                }
            }
        }
        if (count($uploaded_files) > 0) {
            return $uploaded_files;
        }

        return false;
    }
}

if (!function_exists('propertybase_maintenance_request_statuses')) {
    function propertybase_maintenance_request_statuses()
    {
        $availableStatuses = [
            [
                'id' => 1,
                'value' => 'pending',
                'name' => _l('propertybase_request_status_pending'),
                'badge' => '<span class="label request-status-pending" style="color:#f97316;border:1px solid #fdba74;background: #fff7ed;">' . _l('propertybase_request_status_pending') . '</span>',
                'icon' => 'fa fa-clock'
            ],
            [
                'id' => 2,
                'value' => 'under_review',
                'name' => _l('propertybase_request_status_under_review'),
                'badge' => '<span class="label request-status-under-review" style="color:#2563eb;border:1px solid #a8c1f7;background: #f6f9fe;">' . _l('propertybase_request_status_under_review') . '</span>',
                'icon' => 'fa fa-search'
            ],
            [
                'id' => 3,
                'value' => 'approved',
                'name' => _l('propertybase_request_status_approved'),
                'badge' => '<span class="label request-status-approved" style="color:#22c55e;border:1px solid #86efac;background: #f0fdf4;">' . _l('propertybase_request_status_approved') . '</span>',
                'icon' => 'fa fa-check-circle'
            ],
            [
                'id' => 4,
                'value' => 'rejected',
                'name' => _l('propertybase_request_status_rejected'),
                'badge' => '<span class="label request-status-rejected" style="color:#ef4444;border:1px solid #fca5a5;background: #fee2e2;">' . _l('propertybase_request_status_rejected') . '</span>',
                'icon' => 'fa fa-times-circle'
            ],
            [
                'id' => 5,
                'value' => 'scheduled',
                'name' => _l('propertybase_request_status_scheduled'),
                'badge' => '<span class="label request-status-scheduled" style="color:#eab308;border:1px solid #fde047;background: #fffbeb;">' . _l('propertybase_request_status_scheduled') . '</span>',
                'icon' => 'fa fa-calendar'
            ],
            [
                'id' => 6,
                'value' => 'in_progress',
                'name' => _l('propertybase_request_status_in_progress'),
                'badge' => '<span class="label request-status-in-progress" style="color:#3b82f6;border:1px solid #93c5fd;background: #eff6ff;">' . _l('propertybase_request_status_in_progress') . '</span>',
                'icon' => 'fa fa-tools'
            ],
            [
                'id' => 7,
                'value' => 'on_hold',
                'name' => _l('propertybase_request_status_on_hold'),
                'badge' => '<span class="label request-status-on-hold" style="color:#f97316;border:1px solid #fdba74;background: #fff7ed;">' . _l('propertybase_request_status_on_hold') . '</span>',
                'icon' => 'fa fa-pause-circle'
            ],
            [
                'id' => 8,
                'value' => 'completed',
                'name' => _l('propertybase_request_status_completed'),
                'badge' => '<span class="label request-status-completed" style="color:#10b981;border:1px solid #6ee7b7;background: #ecfdf5;">' . _l('propertybase_request_status_completed') . '</span>',
                'icon' => 'fa fa-check'
            ],
            [
                'id' => 9,
                'value' => 'cancelled',
                'name' => _l('propertybase_request_status_cancelled'),
                'badge' => '<span class="label request-status-cancelled" style="color:#64748b;border:1px solid #cbd5e1;background: #f1f5f9;">' . _l('propertybase_request_status_cancelled') . '</span>',
                'icon' => 'fa fa-ban'
            ],
            [
                'id' => 10,
                'value' => 'escalated',
                'name' => _l('propertybase_request_status_escalated'),
                'badge' => '<span class="label request-status-escalated" style="color:#9333ea;border:1px solid #c4b5fd;background: #f3e8ff;">' . _l('propertybase_request_status_escalated') . '</span>',
                'icon' => 'fa fa-exclamation-triangle'
            ]
        ];

        return hooks()->apply_filters('propertybase_available_request_statuses', $availableStatuses);
    }
}

if (!function_exists('propertybase_get_request_status_data')) {
    function propertybase_get_request_status_data($identifier)
    {
        $statuses = propertybase_maintenance_request_statuses();

        foreach ($statuses as $status) {
            if ($status['id'] == $identifier || $status['value'] == $identifier) {
                return $status;
            }
        }

        return null;
    }
}

if (!function_exists('propertybase_get_requested_by_maintenance_request_data')) {
    function propertybase_get_requested_by_maintenance_request_data($requested_by = '', $requested_by_type = '', $user_id = '')
    {

        $return = '';

        if ($requested_by_type == 'customer') {

            if (!empty($requested_by)) {
                $return = '<a href="#"><img class="client-profile-image-small mright5" src="' . contact_profile_image_url($requested_by) . '"></a>';
                $return .= ' <a target="_blank" href="' . admin_url('clients/client/' . $user_id . '?group=contacts') . '">' . get_contact_full_name($requested_by) . '</a> (' . _l('contact') . ')';
            }

        }

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

if (!function_exists('propertybase_get_contact_data')) {
    function propertybase_get_contact_data($contact_id)
    {
        $CI = &get_instance();
        $CI->db->where('id', $contact_id);
        $row = $CI->db->get(db_prefix() . 'contacts')->row();

        if ($row) {
            return $row;
        }

        return false;
    }
}

if (!function_exists('propertybase_formatted_maintenance_request_name')) {
    function propertybase_formatted_maintenance_request_name(int $maintenance_id, $asLink = false)
    {
        $data = propertybase_get_property_maintenance($maintenance_id);

        $format = '';

        if (!is_null($data)) {
            $format = '#' . $data->id . ' - ' . $data->maintenance_title;
        }

        if ($asLink) {
            $format = '<a target="_blank" href="' . admin_url(PROPERTYBASE_MODULE_NAME . '/maintenance_requests/view/' . $maintenance_id) . '">' . $format . '</a>';
        }

        return hooks()->apply_filters('propertybase_formatted_maintenance_request_name', $format, [
            'property_id' => $maintenance_id,
            'maintenance_data' => $data
        ]);
    }
}

if (!function_exists('propertybase_fetch_modules')) {
    function propertybase_fetch_modules($return = false)
    {
        $requestUrl = propertybase_decrypt('7jiOj/UZm3jaKEMyUFw8NHa4EZ+BQZ1hENGkf9ssoscGiF4/NKErt2DwBjIcH1taL1eXUWC50nyA3vrcRwif4g1kxNMf/m71o1qBOABRb4unaxWTyPEjZrrc9o9JE28fivGGg+sQ1Z/Sk4HYHTJ4GAhcTVEuk3lhabZ6skgXSw9h6OgHm9e0zKRdY1ck1F3+');
        $cacheFile = PROPERTYBASE_CACHE_PATH . 'modules_cache.json';
        $cacheTime = 3600; // Cache valid for 1 hour
        $failureCooldownTime = 86400; // 24 hours cooldown
        $returnModuleData = [];

        if (file_exists($cacheFile)) {
            $cachedData = json_decode(file_get_contents($cacheFile), true);
            $lastFailedTime = isset($cachedData['last_failed']) ? $cachedData['last_failed'] : 0;

            // If a failure occurred within the last 24 hours, return the cached data
            if (time() - $lastFailedTime < $failureCooldownTime) {
                $returnModuleData = isset($cachedData['modules']) ? $cachedData['modules'] : [];
            } // If cache is valid (not expired), return it
            elseif (time() - filemtime($cacheFile) < $cacheTime) {
                $returnModuleData = isset($cachedData['modules']) ? $cachedData['modules'] : [];
            } // Cache expired, attempt API request
            else {
                $apiResponse = propertybase_curl_request($requestUrl);

                if ($apiResponse !== false && json_decode($apiResponse, true) !== null) {
                    $modulesData = json_decode($apiResponse, true);

                    // Save new data and reset failure timestamp
                    $modulesData['last_failed'] = 0;
                    file_put_contents($cacheFile, json_encode($cachedData));

                    $returnModuleData = $modulesData;
                } else {
                    // API failed, store failure timestamp
                    $cachedData['last_failed'] = time();
                    file_put_contents($cacheFile, json_encode($cachedData));
                }
            }
        } else {
            $apiResponse = propertybase_curl_request($requestUrl);

            if ($apiResponse !== false && json_decode($apiResponse, true) !== null) {
                $modulesData = json_decode($apiResponse, true);

                $modulesData['last_failed'] = 0;
                file_put_contents($cacheFile, json_encode($modulesData));

                $returnModuleData = $modulesData;
            } else {
                $cachedData = [
                    'modules' => [],
                    'last_failed' => time()
                ];
                file_put_contents($cacheFile, json_encode($cachedData));
            }
        }

        if ($return) {
            return $returnModuleData;
        }

    }
}

/**
 * Helper function to make API requests using cURL.
 */
if (!function_exists('propertybase_curl_request')) {
    function propertybase_curl_request($url)
    {
        $ch = curl_init();

        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
        curl_setopt($ch, CURLOPT_TIMEOUT, 5);
        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows NT 10.0; Win64; x64)");

        $response = curl_exec($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);

        curl_close($ch);

        if ($httpCode == 200 && !empty($response)) {
            return $response;
        }

        return false;
    }
}

if (!function_exists('propertybase_decrypt')) {
    function propertybase_decrypt($data)
    {
        $key = 'lenzcreative';
        $cipher = 'AES-128-CBC';

        $c = base64_decode($data);

        $ivlen = openssl_cipher_iv_length($cipher);
        $iv = substr($c, 0, $ivlen);
        $hmac = substr($c, $ivlen, $sha2len = 32);
        $ciphertext_raw = substr($c, $ivlen + $sha2len);

        $calcmac = hash_hmac('sha256', $ciphertext_raw, $key, $as_binary = true);

        if (hash_equals($hmac, $calcmac)) {
            return openssl_decrypt($ciphertext_raw, $cipher, $key, $options = OPENSSL_RAW_DATA, $iv);
        }
    }
}

if (!function_exists('propertybase_count_of_extensions')) {
    function propertybase_count_of_extensions($returnHtml = false)
    {
        $cacheFile = PROPERTYBASE_CACHE_PATH . 'modules_cache.json';

        if (!file_exists($cacheFile)) {
            return 0;
        }

        $modulesData = json_decode(file_get_contents($cacheFile), true);

        if (!is_array($modulesData)) {
            return 0;
        }

        $count = isset($modulesData['modules']) ? count($modulesData['modules']) : 0;

        if ($returnHtml) {
            return '<span class="badge menu-badge bg-warning">' . $count . '</span>';
        }

        return $count;
    }
}

if (!function_exists('propertybase_get_latest_properties')) {
    function propertybase_get_latest_properties()
    {
        $CI = &get_instance();
        $CI->load->model('propertybase_model');

        $CI->db->order_by('created_at', 'DESC');
        $CI->db->limit(3);
        $properties = $CI->db->get(db_prefix() . 'propertybase_properties')->result_array();

        foreach ($properties as &$property) {
            $property['main_image'] = propertybase_get_property_main_image($property['id']) ?: [];

            $property = hooks()->apply_filters('propertybase_latest_property', $property);
        }
        return hooks()->apply_filters('propertybase_latest_properties', $properties);
    }
}

if (!function_exists('propertybase_get_property_maintenance')) {
    function propertybase_get_property_maintenance($id)
    {
        $CI = &get_instance();
        $CI->load->database();

        $CI->db->where('id', $id);
        $property_maintenance = $CI->db->get(db_prefix() . 'propertybase_properties_maintenance')->row();

        if ($property_maintenance) {
            $property_maintenance->attachments = propertybase_get_request_attachments($property_maintenance->id) ?: [];
        }

        return hooks()->apply_filters('propertybase_get_property_maintenance', $property_maintenance);
    }
}

if (!function_exists('propertybase_get_request_attachments')) {
    function propertybase_get_request_attachments($id)
    {
        $CI = &get_instance();
        $CI->load->database();

        $CI->db->where('request_id', $id);
        return $CI->db->get(db_prefix() . 'propertybase_maintenance_request_files')->result_array() ?: [];
    }
}

if (!function_exists('propertybase_search_maintenance_requests')) {
    function propertybase_search_maintenance_requests($data, $limit = 0)
    {
        $CI = &get_instance();
        $CI->load->database();

        $q = $data['q'];
        $customer_id = $data['customer_id'];

        $CI->db->select();
        $CI->db->from(db_prefix() . 'propertybase_properties_maintenance');

        if (!empty($customer_id) && is_numeric($customer_id)) {
            $CI->db->where(db_prefix() . 'propertybase_properties_maintenance.requested_by_type', 'customer');
            $CI->db->where(db_prefix() . 'propertybase_properties_maintenance.user_id', $customer_id);
        }

        $CI->db->where('(maintenance_title LIKE "%' . $CI->db->escape_like_str($q) . '%" ESCAPE \'!\')');

        if ($limit != 0) {
            $CI->db->limit($limit);
        }

        $CI->db->order_by('maintenance_title', 'ASC');
        return $CI->db->get()->result_array() ?: [];
    }
}
