<?php

namespace Bricksforge\ProForms\Actions;

if (!defined('ABSPATH')) exit; // Exit if accessed directly

class Base
{
    private $settings;
    private $fields;
    private $uploaded_files;
    private $processed_files = [];
    private $file_field_ids = [];
    private $post_id;
    private $dynamic_post_id;
    private $post_context;
    private $form_id;
    private $structure;

    // Live Values
    private $current_proceeding_action;
    private $live_post_id;
    private $live_user_id;
    private $live_pdf_url;
    private $live_pdf_path;
    private $live_pdf_id;

    // Files
    private $processed_file_cache = [];

    public $results;

    // Add a static property to track globally processed files across all Base instances
    protected static $globally_processed_files = [];

    public function __construct($form_settings, $form_data, $form_files, $post_id, $form_id, $dynamic_post_id, $form_structure, $post_context)
    {
        $this->settings = $form_settings;
        $this->fields = $form_data;
        $this->uploaded_files = isset($form_files) ? $form_files : [];
        $this->post_id = $post_id;
        $this->form_id = $form_id;
        $this->dynamic_post_id = $dynamic_post_id;
        $this->post_context = $post_context;
        $this->structure = $form_structure;

        $this->handle_file_field_ids();
    }

    public function get_settings()
    {
        return $this->settings;
    }

    public function get_fields()
    {
        return $this->fields;
    }

    public function get_post_id()
    {
        return $this->post_id;
    }

    public function get_dynamic_post_id()
    {
        return $this->dynamic_post_id;
    }

    public function get_post_context()
    {
        return $this->post_context;
    }

    public function get_form_id()
    {
        return $this->form_id;
    }

    public function get_uploaded_files()
    {
        return $this->uploaded_files;
    }

    public function get_file_field_ids()
    {
        return $this->file_field_ids;
    }

    public function get_current_proceeding_action()
    {
        return $this->current_proceeding_action;
    }

    public function get_live_post_id()
    {
        return $this->live_post_id;
    }

    public function get_live_user_id()
    {
        return $this->live_user_id;
    }

    public function get_live_pdf_url()
    {
        return $this->live_pdf_url;
    }

    public function get_live_pdf_path()
    {
        return $this->live_pdf_path;
    }

    public function get_live_pdf_id()
    {
        return $this->live_pdf_id;
    }

    public function get_structure()
    {
        return $this->structure;
    }

    public function update_live_post_id($post_id)
    {
        $this->live_post_id = $post_id;
    }

    public function update_live_user_id($user_id)
    {
        $this->live_user_id = $user_id;
    }

    public function is_live_id($input)
    {
        if (!isset($input) || !$input) {
            return false;
        }

        $live_values = ["{{live_post_id}}", "{{live_user_id}}"];

        $trimmed_input = trim($input);

        if (in_array($trimmed_input, $live_values)) {
            return true;
        }

        return false;
    }

    public function update_live_pdf_url($pdf_path)
    {
        $this->live_pdf_url = $pdf_path;
    }

    public function update_live_pdf_path($pdf_path)
    {
        $this->live_pdf_path = $pdf_path;
    }

    public function update_live_pdf_id($pdf_id)
    {
        $this->live_pdf_id = $pdf_id;
    }

    public function update_proceeding_action($action)
    {
        $this->current_proceeding_action = $action;
    }

    private function handle_file_field_ids()
    {
        foreach ($this->uploaded_files as $key => $value) {
            foreach ($value as $file) {
                $field_id = substr($file['field'], strpos($file['field'], 'form-field-') + strlen('form-field-'));
                $this->file_field_ids[] = $field_id;
            }
        }
    }

    /**
     * Set action result
     *
     * type: success OR danger
     *
     * @param array $result
     * @return void
     */
    public function set_result($result)
    {
        $type = isset($result['type']) ? $result['type'] : 'success';

        // If type is success, add the $settings['successMessage'] as message
        if ($type === 'success') {

            if (isset($result["message"]) && $result["message"]) {
                $result["message"] = $this->get_form_field_by_id($result["message"]);
            } else {
                $result['message'] = isset($this->settings['successMessage']) ? $this->get_form_field_by_id($this->settings['successMessage']) : __('Message successfully sent. We will get back to you as soon as possible.', 'bricksforge');
            }
        }

        $this->results[$type][] = $result;
    }

    /**
     * Log action error and send JSON error response
     * Helper method to handle actions that need to exit early with wp_send_json_error
     *
     * @param string $action_name
     * @param string $error_message
     * @return void (exits with wp_send_json_error)
     */
    public function log_error_and_exit($action_name, $error_message)
    {
        // Set the result first
        $this->set_result([
            'action' => $action_name,
            'type' => 'error',
            'message' => $error_message,
        ]);

        // Log the error before exiting
        require_once(BRICKSFORGE_PATH . '/includes/elements/pro-forms/ProFormsLogger.php');
        \Bricksforge\ProForms\ProFormsLogger::log(
            $action_name,
            'error',
            "Action '$action_name' failed",
            ['error_message' => $error_message],
            $this->get_form_id(),
            $this->get_post_id()
        );

        // Send JSON error and exit
        wp_send_json_error([
            'message' => $error_message
        ]);
    }

    /**
     * This function is used to get the value of a form field by its ID.
     *
     * @param [type] $id
     * @param [type] $form_data
     * @param [type] $current_post_id
     * @param [type] $form_settings
     * @param [type] $form_files
     * @param boolean $implode_array
     * @param boolean $force_file_url_output
     * @param boolean $ignore_files
     * @param boolean $use_label
     * @param boolean $use_field_label
     * @param [type] $source (ACF, Metabox, ACPT)
     * @return void
     */
    public function get_form_field_by_id($id, $form_data = null, $current_post_id = null, $form_settings = null, $form_files = null, $implode_array = true, $force_file_url_output = false, $ignore_files = false, $use_label = false, $use_field_label = false, $source = null)
    {
        // Track if :array modifier was requested
        $force_array_output = false;

        // We render dynamic data for nested tags
        if (isset($this->dynamic_post_id) && $this->dynamic_post_id) {
            $id = bricks_render_dynamic_data($id, $this->dynamic_post_id);
        } else {
            $id = bricks_render_dynamic_data($id, $this->post_id);
        }

        // We replace {{live_post_id}} with the live post ID.
        if ($this->live_post_id) {
            $live_post_id_regex = '/{{live_post_id}}/';
            $id = preg_replace($live_post_id_regex, $this->live_post_id, $id);
        }

        // We replace {{live_user_id}} with the live user ID.
        $live_user_id_regex = '/{{live_user_id}}/';
        if ($this->live_user_id) {
            $id = preg_replace($live_user_id_regex, $this->live_user_id, $id);
        }

        // We replace {{live_pdf_url}} with the live PDF path.
        $live_pdf_url_regex = '/{{live_pdf_url}}/';
        if ($this->live_pdf_url) {
            $id = preg_replace($live_pdf_url_regex, $this->live_pdf_url, $id);
        }

        // We replace {{live_pdf_path}} with the live PDF path.
        $live_pdf_path_regex = '/{{live_pdf_path}}/';
        if ($this->live_pdf_path) {
            $id = preg_replace($live_pdf_path_regex, $this->live_pdf_path, $id);
        }

        // We replace {{live_pdf_id}} with the live PDF id
        $live_pdf_id_regex = '/{{live_pdf_id}}/';
        if ($this->live_pdf_id) {
            $id = preg_replace($live_pdf_id_regex, $this->live_pdf_id, $id);
        }

        // We replace {{all_fields}} with all form fields.
        if ($id == "all_fields" || $id == "{{all_fields}}") {
            return $this->get_all_fields($this->fields);
        }

        // Handle Repeaters
        if (isset($this->fields['brfr'])) {
            $original_text = $id;
            $repeater_implode_array = !strpos($id, ':array');

            // Extract placeholders
            preg_match_all('/{{([^}]+)}}/', $original_text, $matches);

            foreach ($matches[1] as $placeholder) {
                $repeater_id = str_replace([':array', ':implode', ':url'], '', $placeholder);
                $repeater_data = $this->fields['brfr'][$repeater_id] ?? null;

                if ($placeholder == 'all_fields') {
                    $original_text = $this->get_all_fields($this->fields);
                }

                if ($repeater_data) {
                    $replacer_text = $this->handle_repeater_fields($repeater_data, $this->fields, $repeater_implode_array);

                    if (is_string($replacer_text)) {
                        $original_text = str_replace("{{{$placeholder}}}", $replacer_text, $original_text);
                    }
                }
            }

            if (count($matches[1]) === 0) {
                if (isset($this->fields['brfr'][$id])) {
                    $original_text = $this->handle_repeater_fields($this->fields['brfr'][$id], $this->fields, $repeater_implode_array);
                }
            }

            $id = $original_text; // Update $id with processed repeater fields
        }

        foreach ($this->fields as $key => $value) {

            // form-field-{id}
            $field_id = explode('form-field-', $key);
            $field_id = isset($field_id[1]) ? $field_id[1] : null;

            if (!$field_id) {
                // Its not a Form Field. Continue.
                continue;
            }

            // If the ID has the format {{id}} or {{ id }}, we replace the variables with the values
            if (isset($id) && is_string($id) && strpos($id, '{{') !== false) {

                // If contains :url, we set $force_file_url_output to true
                if (strpos($id, ':url') !== false) {
                    $force_file_url_output = true;

                    // Remove :url from $id
                    $id = str_replace(':url', '', $id);
                }

                // If contains :id, we set $force_file_url_output to false
                if (strpos($id, ':id') !== false) {
                    $force_file_url_output = false;

                    // Remove :id from $id
                    $id = str_replace(':id', '', $id);
                }

                // If contains :implode, we set $implode_array to true
                if (strpos($id, ':implode') !== false) {
                    $implode_array = true;

                    // Remove :implode from $id
                    $id = str_replace(':implode', '', $id);
                }

                // If contains :array, we set $implode_array to false and force array output
                if (strpos($id, ':array') !== false) {
                    $implode_array = false;
                    $force_array_output = true;

                    // Remove :array from $id
                    $id = str_replace(':array', '', $id);
                }

                preg_match_all('/{{([^}]+)}}/', $id, $matches);

                // Create a copy of the original ID to work with
                $modified_id = $id;

                foreach ($matches[1] as $match) {
                    $match_use_label = $use_label;
                    $match_use_field_label = $use_field_label;
                    $fallback_value = null;

                    // Map field filter (e.g., :address, :lat, :lng, :coords)
                    $map_filter = null;
                    $map_filters = [':address', ':lat', ':lng', ':coords', ':zoom'];
                    foreach ($map_filters as $filter) {
                        if (strpos($match, $filter) !== false) {
                            $map_filter = $filter;
                            break;
                        }
                    }

                    // Check for @fallback in the match
                    if (strpos($match, '@fallback=') !== false) {
                        // Extract the fallback value
                        preg_match('/@fallback=[\"\']([^\"\']*)[\"\']/', $match, $fallback_matches);
                        if (!empty($fallback_matches[1])) {
                            $fallback_value = $fallback_matches[1];
                        }

                        // Remove the @fallback part from the match
                        $clean_match = preg_replace('/@fallback=[\"\'][^\"\']*[\"\']/', '', $match);
                    } elseif (strpos($match, ':label') !== false) {
                        $match_use_label = true;
                        $clean_match = str_replace(':label', '', $match);
                    } elseif (strpos($match, '@label') !== false) {
                        $match_use_field_label = true;
                        $clean_match = str_replace('@label', '', $match);
                    } elseif (strpos($match, ':value') !== false) {
                        $match_use_label = false;
                        $clean_match = str_replace(':value', '', $match);
                    } else {
                        $clean_match = $match;
                        $match_use_label = false; // Default to false for matches without modifiers
                        $match_use_field_label = false;
                    }

                    // Remove map filter from clean_match if present
                    if ($map_filter) {
                        $clean_match = str_replace($map_filter, '', $clean_match);
                    }

                    $value = $this->get_form_field_by_id(trim($clean_match), $form_data, $current_post_id, $form_settings, $form_files, $implode_array, $force_file_url_output, $ignore_files, $match_use_label, $match_use_field_label, $source);

                    // Apply map filter if present
                    if ($map_filter && is_string($value)) {
                        $value = $this->apply_map_filter($value, $map_filter);
                    }

                    // If value is array, we have files. In that case, we replace each of them
                    if (!is_array($value)) {
                        // If the value remains the same or is empty, check if we have a fallback
                        if (($value === $clean_match || empty($value)) && $fallback_value !== null) {
                            $modified_id = str_replace('{{' . $match . '}}', $fallback_value, $modified_id);
                        } else if ($value === $clean_match) {
                            $modified_id = str_replace('{{' . $match . '}}', "", $modified_id);
                        } else {
                            $modified_id = str_replace('{{' . $match . '}}', $value, $modified_id);
                        }
                    } else {
                        if (empty($value) && $fallback_value !== null) {
                            $modified_id = str_replace('{{' . $match . '}}', $fallback_value, $modified_id);
                        } else if ($implode_array && !$this->is_file($clean_match)) {
                            $modified_id = str_replace('{{' . $match . '}}', implode(', ', $value), $modified_id);
                        } else {
                            $modified_id = str_replace('{{' . $match . '}}', $clean_match, $modified_id);
                        }
                    }
                }

                // Update $id with all replacements processed
                $id = $modified_id;
            }

            if ($field_id === $id || $field_id === $id  . '[]') {

                // $field_structure -> $this->structure with field_id == $field_id
                $filtered_structure = array_filter($this->structure, function ($field) use ($field_id) {
                    // Check if the current field matches
                    if (isset($field['field_id']) && $field['field_id'] === $field_id) {
                        return true;
                    }

                    // Recursively search through children if they exist
                    if (isset($field['children']) && is_array($field['children'])) {
                        foreach ($field['children'] as $child) {
                            if (isset($child['field_id']) && $child['field_id'] === $field_id) {
                                return true;
                            }

                            // Search deeper in nested children
                            if (isset($child['children']) && is_array($child['children'])) {
                                $found = array_filter($child['children'], function ($grandchild) use ($field_id) {
                                    return isset($grandchild['field_id']) && $grandchild['field_id'] === $field_id;
                                });
                                if (!empty($found)) {
                                    return true;
                                }
                            }
                        }
                    }

                    return false;
                });

                // Get the actual field data from the filtered structure
                $field_structure = null;
                foreach ($filtered_structure as $structure) {
                    // Check direct match
                    if (isset($structure['field_id']) && $structure['field_id'] === $field_id) {
                        $field_structure = $structure;
                        break;
                    }

                    // Check in children
                    if (isset($structure['children']) && is_array($structure['children'])) {
                        foreach ($structure['children'] as $child) {
                            if (isset($child['field_id']) && $child['field_id'] === $field_id) {
                                $field_structure = $child;
                                break 2;
                            }

                            // Check in grandchildren
                            if (isset($child['children']) && is_array($child['children'])) {
                                foreach ($child['children'] as $grandchild) {
                                    if (isset($grandchild['field_id']) && $grandchild['field_id'] === $field_id) {
                                        $field_structure = $grandchild;
                                        break 3;
                                    }
                                }
                            }
                        }
                    }
                }

                if ($use_label) {
                    $value = $this->get_checkbox_radio_select_label_by_key($field_id, $value, $field_structure);
                }

                $field_name = null;

                if ($field_structure) {
                    $field_name = $field_structure["name"];
                    $field_label = $field_structure["field_label"] ?? null;

                    if ($use_field_label && $field_label) {
                        $value = $field_label;
                        return bricks_render_dynamic_data($value, $this->post_id);
                    }

                    // Handle Date Format
                    if ($field_name === "date") {
                        $date_format_database = isset($field_structure["settings"]["dateFormatDatabase"]) ? $field_structure["settings"]["dateFormatDatabase"] : null;

                        if ($date_format_database) {
                            $value = date($date_format_database, strtotime($value));
                        }
                    }
                }

                // Check if there are files in the form data
                if (isset($this->uploaded_files) && !empty($this->uploaded_files) && !$ignore_files) {

                    // If there are files, check if the current field is a file field
                    foreach ($this->uploaded_files as $field => $files) {

                        foreach ($files as $file) {

                            // $field is form-field-my_field. Strip the "form-field-" part concretely
                            $field = substr($file['field'], strpos($file['field'], 'form-field-') + strlen('form-field-'));

                            if ($field === $id) {

                                // Check if the file has already been processed
                                if ($this->file_in_cache($id)) {
                                    return $this->get_file_from_cache($id);
                                }

                                // If it is a file field, handle this file.
                                $file_url = $this->handle_file($id, $form_settings, $this->uploaded_files, 'url', $force_file_url_output, false, null, $source);

                                if ($file_url) {
                                    $this->processed_file_cache[$id] = $file_url;

                                    return $file_url;
                                }
                            }
                        }
                    }
                } else if ($ignore_files && $this->current_proceeding_action === 'email' && isset($this->uploaded_files) && !empty($this->uploaded_files) && isset($field_structure) && isset($field_structure["name"]) && $field_structure["name"] === "file") {

                    if (!isset($this->uploaded_files["form-field-$id"]) || empty($this->uploaded_files["form-field-$id"])) {
                        return '';
                    }

                    $files = $this->uploaded_files["form-field-$id"];

                    $file_urls = array_map(function ($file) use ($id, $form_settings) {
                        $url = $this->handle_file($id, $form_settings, $this->uploaded_files, 'url', true, false, null, $source);
                        return is_array($url) ? implode(', ', $url) : $url;
                    }, $files);

                    return implode(', ', array_unique($file_urls));
                }

                // Handle base64 strings (for example coming from signature fields)
                if (is_string($value) && strpos($value, 'data:image') !== false) {
                    $base64_string = $value;
                    $base64_location = 'mediaLibrary';

                    if (isset($field_structure) && $field_structure && isset($field_structure["settings"]["uploadLocation"]) && $field_structure["settings"]["uploadLocation"] == "custom" && isset($field_structure["settings"]["uploadDirectory"])) {
                        $base64_location = $field_structure["settings"]["uploadDirectory"];

                        if (!$base64_location) {
                            $base64_location = 'mediaLibrary';
                        }
                    }

                    $base64_image_url = $this->handle_base64_string($base64_string, $force_file_url_output, $base64_location);

                    if ($base64_image_url) {
                        return $base64_image_url;
                    }
                }

                // If $value is an empty array, return empty string or empty array based on force_array_output
                if (is_array($value) && empty($value)) {
                    return $force_array_output ? [] : '';
                }

                // If $value is an array, return comma separated values
                if (is_array($value) && $implode_array) {
                    // Remove 0 values
                    $value = array_filter($value, function ($v) {
                        return $v !== '0';
                    });

                    // Re-index the array
                    $value = array_values($value);

                    // If is not empty, return comma separated values
                    if (is_array($value) && !empty($value)) {

                        // If the array has 5 items and the second item contains "http", we return the second item because it's a file
                        if (count($value) === 5 && strpos($value[1], 'http') !== false) {
                            return $value[1];
                        }

                        return implode(', ', bricks_render_dynamic_data($value, $this->post_id));
                    } else {
                        return $force_array_output ? [] : '';
                    }
                }

                $result = bricks_render_dynamic_data($value, $this->post_id);
                return $force_array_output && !is_array($result) ? [$result] : $result;
            }
        }

        $result = bricks_render_dynamic_data($id, $this->post_id);

        if (!$result) {
            $result = bricks_render_dynamic_data($id, $this->dynamic_post_id);
        }

        // Reset Processed Files Array
        $this->processed_files = [];

        // Ensure array output if :array modifier was requested
        return $force_array_output && !is_array($result) ? [$result] : $result;
    }

    /**
     * Get the label of a checkbox, radio or select field by the key
     *
     * @param string $key
     * @param string|array $value
     * @param array $structure
     * @return string|array
     */
    public function get_checkbox_radio_select_label_by_key($key, $value, $structure)
    {

        // structure -> children -> field_label
        if (!is_array($value)) {
            $value = [$value];
        }

        $value = array_map(function ($v) use ($key, $structure) {
            $structure_children = $structure['children'];

            // If the structure has a children with field_value == $v, we return the field_label
            if (is_array($structure_children) && !empty($structure_children)) {
                $filtered_children = array_filter($structure_children, function ($child) use ($v, $key) {
                    return $child['field_id'] === $key && $child['field_value'] === $v;
                });

                if (!$filtered_children) {
                    $checkbox_radio_labels = isset($_POST['checkboxRadioLabels']) ? json_decode(stripslashes($_POST['checkboxRadioLabels']), true) : [];

                    if (isset($checkbox_radio_labels[$key]) && is_array($checkbox_radio_labels[$key])) {
                        foreach ($checkbox_radio_labels[$key] as $label) {
                            if ($label['value'] === $v && $label['label']) {
                                return $label['label'];
                            }
                        }
                    }
                }

                $field_label = reset($filtered_children);

                if ($field_label) {
                    return $field_label['field_label'];
                }
            }

            return $v;
        }, $value);

        return $value;
    }

    /**
     * Get the calculation value by the field ID
     *
     * @param string $id
     * @param string $value
     * @return string
     */
    public function get_calculation_value_by_id($id, $value)
    {
        // In the form settings, we search the id and check for calculationValue
        $calculation_value = null;

        $filtered_settings = array_filter($this->structure, function ($field) use ($id) {
            return $field['field_id'] === $id;
        });
        $settings = reset($filtered_settings);

        if ($settings) {
            // We check also for the $value
            // If the "children" key contains the value (field_value), we return the calculationValue
            $filtered_children = array_filter($settings['children'], function ($child) use ($value) {
                return $child['settings']['value'] === $value && isset($child['settings']['calculationValue']);
            });
            $calculation_value = reset($filtered_children);

            if ($calculation_value) {
                return $calculation_value['settings']['calculationValue'];
            }
        }

        return $value;
    }

    public function get_all_fields($form_data)
    {
        $fields = [];

        foreach ($form_data as $key => $value) {
            $field_id = explode('form-field-', $key);
            $field_id = isset($field_id[1]) ? $field_id[1] : null;

            if (!$field_id) {
                // Check if its a repeater. If not, continue
                if ($key !== 'brfr') {
                    continue;
                }

                // The Field ID is the first key of the array
                $field_id = key($value);
            }

            // We parse base64 strings as images
            if (is_string($value) && strpos($value, 'data:image') !== false) {
                $fields[$field_id] = '<br><img src="' . $value . '" style="max-width: 200px; height: auto;" />';
                continue;
            }

            // If value is empty, we don't add it to the array
            if (empty($value)) {
                continue;
            }

            $fields[$field_id] = $value;
        }

        // If there are no fields, return an empty string
        if (empty($fields)) {
            return "";
        }

        // We implode the array. One field per line
        $fields = array_map(function ($value, $key) {
            $field_id = $key;
            $label = $this->get_label_by_key($key);

            if ($label) {
                $key = $label;
            }

            // If we have an repeater field, we handle it
            if (isset($this->fields['brfr']) && isset($this->fields['brfr'][$field_id])) {
                $value = $this->handle_repeater_fields($this->fields['brfr'][$field_id], $this->fields, true);

                if (is_string($value) && $value) {
                    return $key . ': ' . $value;
                }
            }

            // Check for files
            if ($this->is_file($field_id)) {
                $file_urls = $this->handle_file($field_id, $this->settings, $this->uploaded_files, 'url', true, false, null, $source);
                if (is_array($file_urls)) {
                    $value = implode(', ', $file_urls);
                } else {
                    $value = $file_urls;
                }
            }

            // If value is an array, join it with a comma
            if (is_array($value)) {
                // We remove 0 values
                $value = array_filter($value, function ($v) {
                    return $v !== '0';
                });

                // If is not empty, return comma separated values
                if (!empty($value)) {
                    $value = implode(', ', $value);
                } else {
                    return '';
                }
            }

            return $key . ': ' . $value;
        }, $fields, array_keys($fields));

        $result = implode("<br>", $fields);

        return $result;
    }

    public function handle_repeater_fields($repeater_data, $form_data = null, $implode_array = true)
    {
        $delimiter = ' ' . '+++' . ' ';

        if (!$repeater_data || !is_array($repeater_data) || empty($repeater_data)) {
            return [];
        }

        $organized_repeater_data = [];

        // Directly iterate through each item in the repeater data
        foreach ($repeater_data as $item_index => $fields) {

            foreach ($fields as $field_name => $field_value) {

                $is_file = is_array($field_value) && isset($field_value['file']) && isset($field_value['url']) && isset($field_value['type']) && isset($field_value['itemIndex']);

                if ($is_file) {

                    $file_id = $field_value['subFieldId'];
                    $item_index = $field_value['itemIndex'];
                    $file_url = $field_value['url'];

                    $attachment_id = $this->handle_file($file_id, $this->settings, $this->uploaded_files, 'id', false, true, $item_index);

                    if ($attachment_id) {
                        $field_value = $attachment_id;
                    } else {
                        $field_value = $file_url;
                    }
                } else {
                    // If the field value is an array with only one item, we take the first item (checkboxes, for example)
                    if (is_array($field_value) && count($field_value) === 1) {
                        $field_value = $field_value[0];
                    }
                }

                // Organize data by item index and field name
                $organized_repeater_data[$item_index][$field_name] = $field_value;
            }
        }

        // We join the array with a comma
        if ($implode_array) {
            $string_output = array_map(function ($item) {
                // Filter out empty values to avoid entries like "Color: "
                $filtered_item = array_filter($item, function ($value) {
                    return !empty($value);
                });
                // Convert each field into "Label: Value"
                $item_parts = array_map(function ($value, $key) {

                    // If value is an array, join it with a comma
                    if (is_array($value)) {
                        // We remove 0 values
                        $value = array_filter($value, function ($v) {
                            return $v !== '0';
                        });

                        // If is not empty, return comma separated values
                        if (!empty($value)) {
                            $value = implode(', ', $value);
                        } else {
                            return '';
                        }
                    }

                    return $this->get_label_by_key($key) . ': ' . $value; // Capitalize the label for better readability
                }, $filtered_item, array_keys($filtered_item));
                // Join all parts for the current item with a comma
                return implode(', ', $item_parts);
            }, $organized_repeater_data);

            // Join all items with a pipe
            return implode($delimiter, $string_output);
        }

        return json_encode($organized_repeater_data);
    }

    public function get_label_by_key($key)
    {
        $field_labels = isset($_POST['fieldLabels']) ? json_decode(stripslashes($_POST['fieldLabels']), true) : [];

        $matching = $field_labels[$key] ?? $key;
        $matching = $field_labels["brfr_{$key}"] ?? $matching; // Check for repeater labels

        if ($matching) {
            return $matching;
        }

        return "Field";
    }

    /**
     * Apply map field filter to extract specific data from map JSON
     *
     * @param string $value The JSON value from the map field
     * @param string $filter The filter to apply (:address, :lat, :lng, :coords, :zoom)
     * @return string The filtered value
     */
    public function apply_map_filter($value, $filter)
    {
        // Try to decode as JSON
        $decoded = json_decode($value, true);

        // If not valid JSON or not a map object, return original value
        if (!is_array($decoded) || !isset($decoded['lat']) || !isset($decoded['lng'])) {
            return $value;
        }

        switch ($filter) {
            case ':address':
                return $decoded['address'] ?? '';
            case ':lat':
                return (string) ($decoded['lat'] ?? '');
            case ':lng':
                return (string) ($decoded['lng'] ?? '');
            case ':coords':
                return ($decoded['lat'] ?? '') . ',' . ($decoded['lng'] ?? '');
            case ':zoom':
                return (string) ($decoded['zoom'] ?? '');
            default:
                return $value;
        }
    }

    public function is_file($id)
    {
        // If the ID is included in the file_field_ids array, return true
        if (in_array($id, $this->file_field_ids)) {
            return true;
        }

        return false;
    }

    public function get_structure_element_by_id($id)
    {
        // Return early if no ID provided
        if (!$id) {
            return null;
        }

        // Return early if no structure exists
        if (!$this->structure || !is_array($this->structure)) {
            return null;
        }

        // Use recursive search to find the element
        $result = $this->search_structure_recursively($this->structure, $id);

        return $result;
    }

    /**
     * Recursively search through structure to find element by field_id
     *
     * @param array $structure
     * @param string $id
     * @return array|null
     */
    private function search_structure_recursively($structure, $id)
    {
        if (!is_array($structure)) {
            return null;
        }

        foreach ($structure as $element) {
            // Check if current element matches exactly
            if (isset($element['field_id']) && $element['field_id'] === $id) {
                return $element;
            }

            // Check if current element matches after removing dynamic placeholders
            // This handles cases where the structure contains placeholders like {post_id}
            if (isset($element['field_id'])) {
                $static_part = $this->remove_dynamic_placeholders($element['field_id']);
                $search_static_part = $this->remove_dynamic_placeholders($id);


                // Check if static parts match OR if search ID starts with static part
                // This handles both cases: placeholder in structure vs concrete ID in search
                if (($static_part === $search_static_part && !empty($static_part)) ||
                    (strpos($id, $static_part) === 0 && !empty($static_part))
                ) {
                    return $element;
                }
            }

            // Recursively search through children if they exist
            if (isset($element['children']) && is_array($element['children']) && !empty($element['children'])) {
                $found = $this->search_structure_recursively($element['children'], $id);
                if ($found !== null) {
                    return $found;
                }
            }
        }

        return null;
    }

    /**
     * Remove dynamic placeholders from field ID to get the static part
     * Examples:
     * "cda578-{post_id}" -> "cda578-"
     * "field-{user_id}-data" -> "field--data"
     * "simple-field" -> "simple-field"
     *
     * @param string $field_id
     * @return string
     */
    private function remove_dynamic_placeholders($field_id)
    {
        if (!$field_id) {
            return '';
        }


        // Remove content within curly braces { }
        $cleaned = preg_replace('/\{[^}]+\}/', '', $field_id);

        // Remove double curly braces {{ }}
        $cleaned = preg_replace('/\{\{[^}]+\}\}/', '', $cleaned);

        // Remove :url suffix if present
        $cleaned = str_replace(':url', '', $cleaned);

        return $cleaned;
    }


    /**
     * Generate a random file name
     * @param $file_name
     * @param $length
     * @return string
     */
    /**
     * Generate a random file name with specified length
     * 
     * @param string $file_name Original file name
     * @param int $length Length of random string to generate
     * @return string Random file name
     */
    public function generate_random_file_name($file_name, $length)
    {
        // Validate inputs
        if (!is_string($file_name) || empty($file_name)) {
            return '';
        }

        // Ensure length is valid
        $length = absint($length);
        if ($length < 1) {
            $length = 8; // Default to 8 characters if invalid length
        }

        // Extract the extension
        $extension = pathinfo(basename($file_name), PATHINFO_EXTENSION);

        // Get just the filename without path or extension
        $file_name = pathinfo(basename($file_name), PATHINFO_FILENAME);

        // Generate random string of specified length using allowed characters
        $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
        $char_length = strlen($characters);
        $random_string = '';

        try {
            for ($i = 0; $i < $length; $i++) {
                $random_string .= $characters[rand(0, $char_length - 1)];
            }
        } catch (\Exception $e) {
            return ''; // Return empty string if random generation fails
        }

        // Append the extension to the random string
        $random_string .= '.' . $extension;

        return $random_string;
    }

    /**
     * Check if the file is in the cache
     * @param $file_id
     * @return bool
     */
    public function file_in_cache($file_id)
    {
        // If file_id is {{id}}, we need to strip the {{ and }} parts
        if (strpos($file_id, '{{') !== false) {
            $file_id = str_replace('{{', '', $file_id);
            $file_id = str_replace('}}', '', $file_id);
        }

        // We check if the file_id is in the cache
        if (isset($this->processed_file_cache[$file_id])) {
            return true;
        }

        return false;
    }

    public function get_file_from_cache($file_id)
    {
        // If file_id is {{id}}, we need to strip the {{ and }} parts
        if (strpos($file_id, '{{') !== false) {
            $file_id = str_replace('{{', '', $file_id);
            $file_id = str_replace('}}', '', $file_id);
        }

        return $this->processed_file_cache[$file_id];
    }

    /**
     * Handle Thumbnail for different actions. 
     * Return the attachment ID
     * @param $thumbnail
     * @param $form_settings
     * @param $form_files
     * @return string
     * 
     */
    public function handle_file($file_id, $form_settings, $form_files, $format = 'id', $force_url_output = false, $is_repeater = false, $item_index = null, $source = null)
    {
        if ($this->file_in_cache($file_id)) {
            return $this->get_file_from_cache($file_id);
        }

        $processed_in_this_call = [];
        $file_element = null;
        $file_element_settings = null;

        if ($file_id && is_string($file_id)) {
            $file_element = $this->get_structure_element_by_id($file_id) ?? null;
            if ($file_element && is_array($file_element) && isset($file_element['settings'])) {
                $file_element_settings = $file_element['settings'];
            }
        }

        $uploaded_files = [];
        $file_array = [];

        if ($file_id && isset($form_files) && count($form_files)) {
            foreach ($form_files as $files) {
                foreach ($files as $file) {
                    // Extrahiere das Feld aus $file['field']
                    $field = substr($file['field'], strpos($file['field'], 'form-field-') + strlen('form-field-'));
                    if ($is_repeater) {
                        $field = $file['subFieldId'];
                    }
                    // Wenn das File nicht zum aktuellen Field gehört, überspringen

                    // If $field_id contains {{id}}, we need to strip the {{ and }} parts
                    if (strpos($file_id, '{{') !== false) {
                        $file_id = str_replace('{{', '', $file_id);
                        $file_id = str_replace('}}', '', $file_id);
                    }

                    if ($field !== $file_id) {
                        continue;
                    }

                    // Erstelle einen globalen Cache-Key, der nur von Dateiname, Inhalt und Format abhängt.
                    $content_hash = (file_exists($file['file'])) ? md5_file($file['file']) : '';
                    $global_cache_key = md5($file['name'] . $content_hash . $format);

                    if (isset(self::$globally_processed_files[$global_cache_key])) {
                        // Füge das gecachte Ergebnis der Ergebnisliste hinzu
                        if (is_array(self::$globally_processed_files[$global_cache_key])) {
                            $file_array = array_merge($file_array, self::$globally_processed_files[$global_cache_key]);
                        } else {
                            $file_array[] = self::$globally_processed_files[$global_cache_key];
                        }
                        continue;
                    }
                    $uploaded_files[] = $file;
                }
            }
        }

        if ($uploaded_files && count($uploaded_files)) {
            foreach ($uploaded_files as $file) {
                // Behandlung von initial hochgeladenen Dateien
                if (isset($file['isInitialFile']) && $file['isInitialFile'] === true) {
                    $initial_file_attachment_id = $file['attachmentId'];
                    $initial_file_url = $file['url'];

                    if ($is_repeater) {
                        $current_proceesing_action = $this->get_current_proceeding_action();
                        switch ($current_proceesing_action) {
                            case 'email':
                                $file_array[] = $initial_file_url;
                                break;
                            default:
                                $file_array[] = $initial_file_attachment_id;
                                break;
                        }
                    } elseif ($format === 'url' && !class_exists('ACF') && !class_exists('RW_Meta_Box') && !class_exists('Jet_Engine')) {
                        $file_array[] = $initial_file_url;
                    } elseif ($format === 'url' && class_exists('Jet_Engine') && !class_exists('RW_Meta_Box') && !class_exists('ACF')) {
                        $file_array[] = $initial_file_url;
                    } elseif ($force_url_output) {
                        $file_array[] = $initial_file_url;
                    } else {
                        $file_array[] = $initial_file_attachment_id;
                    }
                    $this->processed_files[] = $file;
                    // Auch hier wird der globale Cache-Key verwendet
                    $content_hash = (file_exists($file['file'])) ? md5_file($file['file']) : '';
                    $global_cache_key = md5($file['name'] . $content_hash . $format);
                    if (count($file_array) > 0) {
                        $last_index = count($file_array) - 1;
                        self::$globally_processed_files[$global_cache_key] = $file_array[$last_index];
                    }
                    continue;
                }

                $file_name = $file['name'];
                $file_path = $file['file'];

                if ($is_repeater && $file['itemIndex'] != $item_index) {
                    continue;
                }

                if (file_exists($file_path)) {
                    $use_custom_path = isset($file_element_settings['useCustomUploadPath']) && $file_element_settings['useCustomUploadPath'];
                    $custom_path = isset($file_element_settings['customUploadPath']) ? $this->get_form_field_by_id($file_element_settings['customUploadPath']) : '';
                    $skip_media_library = isset($file_element_settings['skipAddToMediaLibrary']) && $file_element_settings['skipAddToMediaLibrary'];
                    $use_random_file_name = isset($file_element_settings['useRandomFileName']) && $file_element_settings['useRandomFileName'];
                    $random_file_name_length = isset($file_element_settings['randomFileNameLength']) ? $this->get_form_field_by_id($file_element_settings['randomFileNameLength']) : 12;

                    if ($use_random_file_name) {
                        $file_name = $this->generate_random_file_name($file_name, $random_file_name_length);
                    }

                    if ($use_custom_path && !empty($custom_path)) {
                        $content_hash = (file_exists($file_path)) ? md5_file($file_path) : '';
                        // Verwende auch hier den globalen Cache-Key, der NICHT vom $file['field'] oder $file_id abhängt
                        $global_cache_key = md5($file['name'] . $content_hash . $format);
                        if (isset(self::$globally_processed_files[$global_cache_key])) {
                            if (is_array(self::$globally_processed_files[$global_cache_key])) {
                                $file_array = array_merge($file_array, self::$globally_processed_files[$global_cache_key]);
                            } else {
                                $file_array[] = self::$globally_processed_files[$global_cache_key];
                            }
                            continue;
                        }

                        $wp_upload_dir = wp_upload_dir();
                        $wp_root_path = ABSPATH;
                        $custom_path = trim($custom_path, '/');
                        $custom_path = str_replace(['..', './', '/.', '\\', ':', '~'], '', $custom_path);
                        $custom_path = preg_replace('/[^a-zA-Z0-9_\-\/]/', '', $custom_path);
                        $custom_path = preg_replace('#/+#', '/', $custom_path);
                        $target_dir = $wp_root_path . $custom_path;

                        if (!file_exists($target_dir)) {
                            wp_mkdir_p($target_dir);
                        }
                        $real_target_dir = realpath($target_dir);
                        $real_wp_root = realpath($wp_root_path);
                        if (!$real_target_dir || strpos($real_target_dir, $real_wp_root) !== 0) {
                            $custom_path = 'wp-content/uploads/';
                            $target_dir = $wp_root_path . $custom_path;
                            error_log('Bricksforge: Directory traversal attempt prevented. Using default upload directory instead.');
                        }
                        if (!file_exists($target_dir)) {
                            wp_mkdir_p($target_dir);
                        }
                        $new_filename = wp_unique_filename($target_dir, $file_name);
                        $new_file_path = $target_dir . '/' . $new_filename;
                        copy($file_path, $new_file_path);

                        if ($skip_media_library) {
                            $new_file_url = site_url() . '/' . $custom_path . '/' . $new_filename;
                            if ($is_repeater) {
                                $current_proceesing_action = $this->get_current_proceeding_action();
                                switch ($current_proceesing_action) {
                                    case 'email':
                                        $file_array[] = $new_file_url;
                                        break;
                                    default:
                                        $file_array[] = $new_file_url;
                                        break;
                                }
                            } elseif ($format === 'url' || $force_url_output) {
                                $file_array[] = $new_file_url;
                            } else {
                                $file_array[] = $new_file_url;
                            }
                            if (count($file_array) > 0) {
                                $last_index = count($file_array) - 1;
                                self::$globally_processed_files[$global_cache_key] = $file_array[$last_index];
                            }
                            $this->processed_files[] = $file;
                            continue;
                        }

                        // If we're not skipping the media library, use the new file path
                        $file_path = $new_file_path;

                        // Also update the URL to match the custom path
                        $custom_path_url = site_url() . '/' . $custom_path . '/' . $new_filename;

                        // Update the attachment array with the custom path information
                        $attachment = array(
                            'guid'           => $custom_path_url,
                            'post_mime_type' => $file['type'],
                            'post_title'     => preg_replace('/\.[^.]+$/', '', basename($new_file_path)),
                            'post_content'   => '',
                            'post_status'    => 'inherit',
                        );

                        $attach_id = wp_insert_attachment($attachment, $new_file_path);

                        require_once ABSPATH . 'wp-admin/includes/image.php';
                        require_once ABSPATH . 'wp-admin/includes/media.php';

                        $attach_data = wp_generate_attachment_metadata($attach_id, $new_file_path);
                        wp_update_attachment_metadata($attach_id, $attach_data);

                        $result_value = null;
                        if ($is_repeater) {
                            $current_proceesing_action = $this->get_current_proceeding_action();
                            switch ($current_proceesing_action) {
                                case 'email':
                                    $result_value = wp_get_attachment_url($attach_id);
                                    $file_array[] = $result_value;
                                    break;
                                default:
                                    $result_value = $attach_id;
                                    $file_array[] = $result_value;
                                    break;
                            }
                        } elseif ($format === 'url' && !class_exists('ACF') && !class_exists('RW_Meta_Box') && !class_exists('Jet_Engine') && !class_exists('ACPT\Includes\ACPT_Plugin')) {
                            $result_value = wp_get_attachment_url($attach_id);
                            $file_array[] = $result_value;
                        } elseif ($format === 'url' && class_exists('Jet_Engine') && !class_exists('RW_Meta_Box') && !class_exists('ACF') && !class_exists('ACPT\Includes\ACPT_Plugin')) {
                            $result_value = wp_get_attachment_url($attach_id);
                            $file_array[] = $result_value;
                        } elseif ($force_url_output) {
                            $result_value = wp_get_attachment_url($attach_id);
                            $file_array[] = $result_value;
                        } else {
                            $result_value = $attach_id;
                            $file_array[] = $result_value;
                        }

                        $content_hash = (file_exists($file['file'])) ? md5_file($file['file']) : '';
                        $global_cache_key = md5($file['name'] . $content_hash . $format);
                        self::$globally_processed_files[$global_cache_key] = $result_value;
                        $this->processed_files[] = $file;
                        continue; // Skip the rest of the processing for this file
                    }

                    if ($skip_media_library && !$use_custom_path) {
                        $wp_upload_dir = wp_upload_dir();
                        $upload_path = $wp_upload_dir['path'];
                        $new_filename = wp_unique_filename($upload_path, $file_name);
                        $new_file_path = $upload_path . '/' . $new_filename;
                        if (copy($file_path, $new_file_path)) {
                            $new_file_url = $wp_upload_dir['url'] . '/' . $new_filename;
                            if ($is_repeater) {
                                $current_proceesing_action = $this->get_current_proceeding_action();
                                switch ($current_proceesing_action) {
                                    case 'email':
                                        $file_array[] = $new_file_url;
                                        break;
                                    default:
                                        $file_array[] = $new_file_url;
                                        break;
                                }
                            } elseif ($format === 'url' || $force_url_output) {
                                $file_array[] = $new_file_url;
                            } else {
                                $file_array[] = $new_file_url;
                            }
                        } else {
                            $file_array[] = $file['url'];
                        }
                        $this->processed_files[] = $file;
                        $content_hash = (file_exists($file_path)) ? md5_file($file_path) : '';
                        $global_cache_key = md5($file['name'] . $content_hash . $format);
                        if (count($file_array) > 0) {
                            $last_index = count($file_array) - 1;
                            self::$globally_processed_files[$global_cache_key] = $file_array[$last_index];
                        }
                        continue;
                    }

                    // Standardvorgang: Datei in die Mediathek einfügen
                    $attachment = array(
                        'guid'           => $file['url'],
                        'post_mime_type' => $file['type'],
                        'post_title'     => preg_replace('/\.[^.]+$/', '', basename($use_random_file_name ? $file_name : $file_path)),
                        'post_content'   => '',
                        'post_status'    => 'inherit',
                    );

                    $wp_upload_dir = wp_upload_dir();
                    $upload_path = $wp_upload_dir['path'];
                    $upload_url = $wp_upload_dir['url'];

                    // Make sure the file is in the WordPress uploads directory with the desired name
                    $desired_filename = basename($attachment['guid']);
                    $destination_path = $upload_path . '/' . $desired_filename;

                    // Copy the file to the desired location if it's not already there
                    if ($file_path !== $destination_path && file_exists($file_path)) {
                        copy($file_path, $destination_path);
                        $file_path = $destination_path;
                    }

                    // Now update the attachment array with the correct information
                    $attachment = array(
                        'guid'           => $upload_url . '/' . basename($file_path),
                        'post_mime_type' => $file['type'],
                        'post_title'     => preg_replace('/\.[^.]+$/', '', basename($file_path)),
                        'post_content'   => '',
                        'post_status'    => 'inherit',
                    );

                    if ($use_random_file_name) {
                        $wp_upload_dir = wp_upload_dir();
                        $upload_path = $wp_upload_dir['path'];
                        $file_extension = pathinfo($file_path, PATHINFO_EXTENSION);
                        if (!preg_match('/\.' . preg_quote($file_extension, '/') . '$/i', $file_name)) {
                            $file_name .= '.' . $file_extension;
                        }
                        $new_filename = wp_unique_filename($upload_path, $file_name);
                        $new_file_path = $upload_path . '/' . $new_filename;
                        copy($file_path, $new_file_path);
                        $file_path = $new_file_path;
                    }

                    $attach_id = wp_insert_attachment($attachment, $file_path);

                    require_once ABSPATH . 'wp-admin/includes/image.php';
                    require_once ABSPATH . 'wp-admin/includes/media.php';

                    $attach_data = wp_generate_attachment_metadata($attach_id, $file_path);

                    wp_update_attachment_metadata($attach_id, $attach_data);

                    $result_value = null;

                    if ($is_repeater) {
                        $current_proceesing_action = $this->get_current_proceeding_action();
                        switch ($current_proceesing_action) {
                            case 'email':
                                $result_value = wp_get_attachment_url($attach_id);
                                $file_array[] = $result_value;
                                break;
                            default:
                                $result_value = $attach_id;
                                $file_array[] = $result_value;
                                break;
                        }
                    } elseif ($source === 'acpt') {
                        $result_value = wp_get_attachment_url($attach_id);
                        $file_array[] = $result_value;
                    } elseif ($source === 'acf') {
                        $result_value = wp_get_attachment_url($attach_id);
                        $file_array[] = $result_value;
                    } elseif ($source === 'metabox') {
                        $result_value = $attach_id;
                        $file_array[] = $result_value;
                    } elseif ($format === 'url' && !class_exists('ACF') && !class_exists('RW_Meta_Box') && !class_exists('Jet_Engine')) {
                        $result_value = wp_get_attachment_url($attach_id);
                        $file_array[] = $result_value;
                    } elseif ($format === 'url' && class_exists('Jet_Engine') && !class_exists('RW_Meta_Box') && !class_exists('ACF')) {
                        $result_value = wp_get_attachment_url($attach_id);
                        $file_array[] = $result_value;
                    } elseif ($force_url_output) {
                        $result_value = wp_get_attachment_url($attach_id);
                        $file_array[] = $result_value;
                    } else {
                        $result_value = $attach_id;
                        $file_array[] = $result_value;
                    }

                    $content_hash = (file_exists($file['file'])) ? md5_file($file['file']) : '';
                    $global_cache_key = md5($file['name'] . $content_hash . $format);
                    self::$globally_processed_files[$global_cache_key] = $result_value;
                    $this->processed_files[] = $file;
                }
            }
        }

        if (count($file_array) === 1) {
            $this->processed_file_cache[$file_id] = $file_array[0];
            $result = $file_array[0];
        } else {
            $this->processed_file_cache[$file_id] = $file_array;
            $result = $file_array;
        }

        return $result;
    }

    public function handle_base64_string($base64_string, $url = false, $location = "mediaLibrary")
    {
        // Set a maximum file size limit (e.g., 2MB)
        $max_file_size = 2 * 1024 * 1024;

        $is_custom_location = $location != "mediaLibrary";

        // Remove the base64 header and decode the string
        $base64_string = str_replace('data:image/png;base64,', '', $base64_string);
        $base64_string = str_replace(' ', '+', $base64_string);
        $binary_data = base64_decode($base64_string, true);

        // Check if the base64 decoding was successful
        if ($binary_data === false) {
            return new WP_Error('invalid_base64', 'Invalid base64 image data.');
        }

        // Check if the file size exceeds the limit
        if (strlen($binary_data) > $max_file_size) {
            return new WP_Error('file_too_large', 'File size exceeds the maximum allowed limit.');
        }

        // Upload Directory
        $upload_dir = wp_upload_dir();
        $upload_path = $upload_dir['path'];
        $upload_url = $upload_dir['url'];

        if ($is_custom_location) {
            $upload_dir = wp_upload_dir();
            $upload_path = $upload_dir['basedir'] . '/' . $location;
            $upload_url = $upload_dir['baseurl'] . '/' . $location;

            // Create the directory if it doesn't exist
            if (!file_exists($upload_path)) {
                mkdir($upload_path, 0755, true);
            }

            // Check if the directory was created successfully
            if (!file_exists($upload_path)) {
                return new WP_Error('directory_creation_failed', 'Failed to create the upload directory.');
            }
        }

        // Generate a unique filename
        $file_name = 'signature-' . time() . '.png';
        $file_name = sanitize_file_name($file_name);

        $file_path = $upload_path . '/' . $file_name;

        // Save the binary data to the upload directory
        $file_saved = file_put_contents($file_path, $binary_data);

        // Check if the file was saved successfully
        if ($file_saved === false) {
            return new WP_Error('file_save_failed', 'Failed to save the file to the upload directory.');
        }

        if (!$is_custom_location) {
            $attachment = array(
                'guid' => $upload_url . '/' . $file_name,
                'post_mime_type' => 'image/png',
                'post_title' => preg_replace('/\.[^.]+$/', '', basename($file_path)),
                'post_content' => '',
                'post_status' => 'inherit',
            );

            $attach_id = wp_insert_attachment($attachment, $file_path);

            if (is_wp_error($attach_id)) {
                // Failed to insert the attachment
                unlink($file_path); // Delete the uploaded file
                return $attach_id;
            }

            require_once ABSPATH . 'wp-admin/includes/image.php';
            require_once ABSPATH . 'wp-admin/includes/media.php';

            $attach_data = wp_generate_attachment_metadata($attach_id, $file_path);
            wp_update_attachment_metadata($attach_id, $attach_data);

            if ($url) {
                return wp_get_attachment_url($attach_id);
            }

            return $attach_id;
        }

        // Custom Location
        return $upload_url . '/' . $file_name;
    }
}
